using adas_core.Application.Customizations.HUVH.UCIN; 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.Utils; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MongoDB.Bson; using Moq; using Newtonsoft.Json; namespace adas_core.Test.Customizations.HUVH.UCIN; [TestFixture] public class CalculatedObservationsTest { [SetUp] public void Setup() { _mockObservationService = new Mock(); _medicineServiceMock = new Mock(); _treatmentServiceMock = new Mock(); _logger = new Mock>(); //JSON data const string mappingInterventionsJson = @"[ { ""Type"": ""Respiratory_Device"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Oxigeno (O2)/Alto flujo"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 204.0, ""FinalValue"": null } ] }, { ""Type"": ""Respiratory_Device"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""CPAP "", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 202.0, ""FinalValue"": null } ] }, { ""Type"": ""Respiratory_Device"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Ventilaci\u00f3n mec\u00e1nica Invasiva"", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 201.0, ""FinalValue"": null } ] }, { ""Type"": ""Respiratory_Device"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VAFO Ventilaci\u00f3n Oscilatoria de alta frecuencia"", ""Value"": [ { ""InitialValue"": 4.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 200.0, ""FinalValue"": null } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VV perfif\u00e9rica"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 103.1, ""FinalValue"": 103.5 } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VV epicut\u00e1neo cava"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 102.1, ""FinalValue"": 102.5 } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VV umbilical"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 101.1, ""FinalValue"": null } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VV central"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 104.1, ""FinalValue"": 104.3 } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VV PICC"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 108.1, ""FinalValue"": 108.2 } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VA umbilical"", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 101.2, ""FinalValue"": null } ] }, { ""Type"": ""Intravenous_Routes"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""VA"", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 106.1, ""FinalValue"": 106.3 } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Digoxina ev"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 118.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Digoxina vo"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 1753.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Amiodarona ev"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 169.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Amiodarona vo"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 16323.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Atropina"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 186.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Esmolol"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 853.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Propranolol"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 7122.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Isoprenalina"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 283.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Flecainida ev"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 1247.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Antiarr\u00edtmicos"", ""Name"": ""Flecainida vo"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 7055.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Adrenalina"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 281.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Noradrenalina"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 100000.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Milrinona"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 618.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Levosimendan"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 2073.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Dopamina"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 149.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Debutamina"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 1968.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Drogas vasoactivas"", ""Name"": ""Fenilefrina"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 12319.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Morfina ev"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 472.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Morfina ov"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 7081.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Fentanil"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 434.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Midazolam"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 756.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Dexmedetomidina"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 15910.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Cisatraculi"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 15066.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Propofol"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 314.0, ""FinalValue"": null } ] }, { ""Type"": ""Medication"", ""Category"": ""Treatment"", ""Group"": ""Sedaci\u00f3n"", ""Name"": ""Ketamina"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 374.0, ""FinalValue"": null } ] }, { ""Type"": ""System"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Hipotermia"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 100001.0, ""FinalValue"": null } ] }, { ""Type"": ""System"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""aEEG"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 100002.0, ""FinalValue"": null } ] }, { ""Type"": ""System"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Drenaje ventricular (DVE)"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 315.1, ""FinalValue"": null }, { ""InitialValue"": 315.2, ""FinalValue"": null } ] }, { ""Type"": ""System"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Drenaje toracico"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 311.0, ""FinalValue"": 314.0 } ] }, { ""Type"": ""System"", ""Category"": ""Intervention"", ""Group"": ""not defined"", ""Name"": ""Dialisis peritoneal - abdominal"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 306.0, ""FinalValue"": 310.0 } ] }, { ""Type"": ""Newborn_Weight"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Newborn_Weight"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": 500.0, ""valueContributed"": 5 }, { ""InitialValue"": 501.0, ""FinalValue"": 1000.0, ""valueContributed"": 4 }, { ""InitialValue"": 1001.0, ""FinalValue"": 1500.0, ""valueContributed"": 3 }, { ""InitialValue"": 1501.0, ""FinalValue"": 2000.0, ""valueContributed"": 2 }, { ""InitialValue"": 2000.0, ""FinalValue"": 2500.0, ""valueContributed"": 1 } ], ""Codes"": [ { ""InitialValue"": 10000465.0, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Cardiaca"", ""Value"": [ { ""InitialValue"": 4.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.1, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Digestiva"", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.2, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Neurologica "", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.3, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Toracica"", ""Value"": [ { ""InitialValue"": 3.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.4, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""ORL/Maxil\u00b7lo"", ""Value"": [ { ""InitialValue"": 2.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.5, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Oftalmo"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.6, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Ortopedia"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.7, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""Altres"", ""Value"": [ { ""InitialValue"": 1.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.8, ""FinalValue"": null } ] }, { ""Type"": ""surgery"", ""Category"": ""Observation"", ""Group"": ""not defined"", ""Name"": ""No"", ""Value"": [ { ""InitialValue"": 0.0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": 14000070.9, ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LM"", ""Name"": ""Llet materna"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIB586"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LM"", ""Name"": ""Llet materna de banc"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIB000589"", ""FinalValue"": null }, { ""InitialValue"": ""BIB000587"", ""FinalValue"": null }, { ""InitialValue"": ""BIB000588"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LM"", ""Name"": ""Llet materna a demanda"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""NO_EST2"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LM descremada"", ""Name"": ""LM descremada"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""NO_EST3"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula de soja"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM003"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula hidrolizada (Alfare)"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM002"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula inici"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBNOR003"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula prematurs 14,4%"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM017"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula prematurs 15,9%"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM018"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Formula sense lactosa"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM01"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Monogen"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBCOM009"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Infatrini"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBNOR001"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Infatini Peptisorb"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBNOR0013"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Neocate 13,8%"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBBAS019"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Neocate Advance 25%"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""NO_EST4"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Energivit"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""BIBBAS021"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""LA"", ""Name"": ""Bibero especial"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""ALTESP001"", ""FinalValue"": null } ] }, { ""Type"": ""Nutrition"", ""Category"": ""Treatment"", ""Group"": ""Absoluta"", ""Name"": ""Absoluta"", ""Value"": [ { ""InitialValue"": 0, ""FinalValue"": null } ], ""Codes"": [ { ""InitialValue"": ""15002284"", ""FinalValue"": null } ] } ]"; const string complexityValuesJson = @"{ ""Oxigeno (O2)/Alto flujo"": 1, ""CPAP "": 2, ""Ventilación mecánica Invasiva"": 3, ""VAFO Ventilación Oscilatoria de alta frecuencia"": 4, ""VV perfiférica"": 1, ""VV epicutáneo cava"": 2, ""VV umbilical"": 2, ""VV central"": 2, ""VV PICC"": 2, ""VA umbilical"": 3, ""VA"": 3, ""Digoxina ev"": 1, ""Digoxina vo"": 1, ""Amiodarona ev"": 1, ""Amiodarona vo"": 1, ""Atropina"": 1, ""Esmolol"": 1, ""Propranolol"": 1, ""Isoprenalina"": 1, ""Flecainida ev"": 1, ""Flecainida vo"": 1, ""Adrenalina"": 2, ""Noradrenalina"": 2, ""Milrinona"": 2, ""Levosimendan"": 2, ""Dopamina"": 2, ""Debutamina"": 2, ""Fenilefrina"": 2, ""Hipotermia"": 2, ""aEEG"": 2, ""Drenaje ventricular (DVE)"": 2, ""Drenaje toracico"": 2, ""Dialisis peritoneal - abdominal"": 2, ""Cardiaca"": 4, ""Digestiva"": 3, ""Neurologica "": 3, ""Toracica"": 3, ""ORL/Maxil·lo"": 2, ""Oftalmo"": 1, ""Ortopedia"": 1, ""Altres"": 1, ""No"": 0 }"; // Deserialize the JSON var apiSettings = JsonConvert.DeserializeObject( $$""" { "MappingInterventions": {{mappingInterventionsJson}}, "ComplexityMappingObservation": {{complexityValuesJson}} } """ ); if (apiSettings == null) return; // Mock IOptions to return our populated ApiSettings _mockApiSettings = new Mock>(); _mockApiSettings.Setup(s => s.Value).Returns(apiSettings); // Create an instance of MappingUtils with the mocked IOptions _mappingUtils = new MappingUtils(_mockApiSettings.Object); var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(new Lazy(() => _mockObservationService.Object)); serviceCollection.AddSingleton(new Lazy(() => _medicineServiceMock.Object)); serviceCollection.AddSingleton(new Lazy(() => _treatmentServiceMock.Object)); serviceCollection.AddSingleton(_mockApiSettings.Object); serviceCollection.AddSingleton(_logger.Object); serviceCollection.AddSingleton(_mappingUtils); // Register the real instance var serviceProvider = serviceCollection.BuildServiceProvider(); _calculatedObservations = new CalculatedObservations(serviceProvider); } private Mock _mockObservationService; private Mock _medicineServiceMock; private Mock _treatmentServiceMock; private Mock> _logger; private Mock> _mockApiSettings; private MappingUtils _mappingUtils; private CalculatedObservations _calculatedObservations; /// /// Verifies that when an observation contains an intervention code (e.g., "204") that exists in the data, /// the Map method creates and inserts a multivalue observation (Respiratory_Device_Multivalue) /// containing the intervention description extracted from the observation value. /// [Test] public async Task Map_WithInterventionCodeInObservationValue_CallsCalculateInterventionMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); var observation = new PatientObservation { Name = "Intervention_In", PatientId = patientId, Value = "204 Oxigeno (O2)/Alto flujo" }; // Code 204 exists in data _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.IsAny>())) .ReturnsAsync([]); // Simulate no existing multivalue observation // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Respiratory_Device_Multivalue") && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Count() == 1 && ((string[])o.Value)[0].ToString() == "Oxigeno (O2)/Alto flujo"), true, true), Times.Once); } /// /// Verifies that mapping an Intervention_Out observation updates an existing active multi-value observation /// (e.g., Respiratory_Device_Multivalue) for the patient by setting its end time, rather than inserting a new observation. /// [Test] public async Task Map_WithInterventionOut_UpdatesExistingMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); var interventionCode = "204"; var interventionDescription = "Oxigeno (O2)/Alto flujo"; var observationOutValue = $"{interventionCode} {interventionDescription}"; var observationOut = new PatientObservation { Name = "Intervention_Out", PatientId = patientId, Value = observationOutValue }; // Simulate an existing multi-value observation that is active var existingMultiValueObservation = new PatientObservation { PatientId = patientId, Name = "Respiratory_Device_Multivalue", Value = new[] { interventionDescription }, Time = DateTime.UtcNow.AddMinutes(-30) // Simulate it started 30 minutes ago }; _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))) // Find the active multi-value observation .ReturnsAsync([existingMultiValueObservation]); // Act await _calculatedObservations.Map(observationOut); // Assert // Verify that the existing multi-value observation was updated to set an EndTime _mockObservationService.Verify( x => x.UpdateObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Respiratory_Device_Multivalue") )), Times.Once); // Optionally, verify that a new observation was NOT inserted _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task Map_WithNewInterventionNoExistingLastIntervention_NewMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); // Simular una intervención activa existente //var existingInterventionCode = "204"; const string existingInterventionDescription = "Oxigeno (O2)/Alto flujo"; var existingMultiValueObservation = new PatientObservation { PatientId = patientId, Name = "Respiratory_Device_Multivalue", Value = new[] { existingInterventionDescription }, Time = DateTime.UtcNow.AddMinutes(-30), Expired = true }; _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))) .ReturnsAsync([existingMultiValueObservation]); // Nuevo evento de "Intervention_In" con una intervención diferente const string newInterventionCode = "202"; const string newInterventionDescription = "CPAP"; const string newObservationInValue = $"{newInterventionCode} {newInterventionDescription}"; var newObservationIn = new PatientObservation { Name = "Intervention_In", PatientId = patientId, Value = newObservationInValue }; // Act await _calculatedObservations.Map(newObservationIn); // Assert // Verificar que NO se insertó una nueva observación (se actualizó la existente) _mockObservationService.Verify( x => x.UpdateObservation(It.IsAny()), Times.Never); // Verificar que la observación multi-valor existente se actualizó añadiendo la nueva intervención _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Respiratory_Device_Multivalue") && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 1 && ((string[])o.Value)[0] != existingInterventionDescription && ((string[])o.Value)[0] != newInterventionDescription), true, true), Times.Once); } [Test] public async Task Map_WithNewInterventionAddsToExistingMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); // Simular una intervención activa existente //var existingInterventionCode = "204"; const string existingInterventionDescription = "Oxigeno (O2)/Alto flujo"; var existingMultiValueObservation = new PatientObservation { PatientId = patientId, Name = "Respiratory_Device_Multivalue", Value = new[] { existingInterventionDescription }, Time = DateTime.UtcNow.AddMinutes(-30) }; _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))) .ReturnsAsync([existingMultiValueObservation]); // Nuevo evento de "Intervention_In" con una intervención diferente const string newInterventionCode = "202"; const string newInterventionDescription = "CPAP"; const string newObservationInValue = $"{newInterventionCode} {newInterventionDescription}"; var newObservationIn = new PatientObservation { Name = "Intervention_In", PatientId = patientId, Value = newObservationInValue }; // Act await _calculatedObservations.Map(newObservationIn); // Assert // Verificar que la observación multi-valor existente se actualizó añadiendo la nueva intervención _mockObservationService.Verify( x => x.UpdateObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Respiratory_Device_Multivalue") && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 1 && ((string[])o.Value)[0] == existingInterventionDescription && o.Expired)), Times.Once); // Verificar que NO se insertó una nueva observación (se actualizó la existente) _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Respiratory_Device_Multivalue") && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 2 && ((string[])o.Value)[0] == existingInterventionDescription && ((string[])o.Value)[1] == newInterventionDescription ), It.IsAny(), It.IsAny()), Times.Never); } /// /// Verifies that mapping a surgery observation inserts a new Surgery_Multivalue observation /// when no existing multi-value observation is found, and does not trigger an update. /// [Test] public async Task Map_WithSurgeryObservation_InsertsNewSurgeryMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); const string surgeryName = "Surgery"; const string surgeryValue = "Appendectomy"; var surgeryObservation = new PatientObservation { Name = surgeryName, PatientId = patientId, Value = surgeryValue }; const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue"; // Simulate no existing Surgery_Multivalue observation _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(expectedMultiValueObservationName)))) .ReturnsAsync([]); // Act await _calculatedObservations.Map(surgeryObservation); // Assert // Verify that a new Surgery_Multivalue observation was inserted with the correct value _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals(expectedMultiValueObservationName) && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 1 && ((string[])o.Value)[0].ToString() == surgeryValue), true, true), Times.Once); // Verify that UpdateObservation was not called _mockObservationService.Verify( x => x.UpdateObservation(It.IsAny()), Times.Never); } /// /// Verifies that mapping a new surgery observation causes an existing "Surgery_Multivalue" patient observation /// to be expired and replaced with a new multi-value observation that contains both the previously recorded /// surgery value and the newly mapped surgery value. /// [Test] public async Task Map_WithSurgeryObservation_UpdatesExistingSurgeryMultiValueObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); const string surgeryName = "Surgery"; const string newSurgeryValue = "Cholecystectomy"; var surgeryObservation = new PatientObservation { Name = surgeryName, PatientId = patientId, Value = newSurgeryValue }; const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue"; const string existingSurgeryValue = "Appendectomy"; var existingMultiValueObservation = new PatientObservation { PatientId = patientId, Name = expectedMultiValueObservationName, Value = new[] { existingSurgeryValue }, Time = DateTime.UtcNow.AddMinutes(-30), Expired = false }; // Simulate an existing Surgery_Multivalue observation _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(expectedMultiValueObservationName)))) .ReturnsAsync([existingMultiValueObservation]); // Act await _calculatedObservations.Map(surgeryObservation); // Assert // Verify that the existing Surgery_Multivalue observation was expired _mockObservationService.Verify( x => x.UpdateObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals(expectedMultiValueObservationName) && o.Expired)), Times.Once); // Verify that a new Surgery_Multivalue observation was inserted with the new value _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals(expectedMultiValueObservationName) && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 2 && ((string[])o.Value)[0].ToString() == existingSurgeryValue && ((string[])o.Value)[1].ToString() == newSurgeryValue), true, true), Times.Once); } /// /// Verifies that mapping a Surgery observation updates the existing Surgery_Multivalue observation by expiring the duplicate entry and inserting a new observation with the duplicate value removed. /// [Test] public async Task Map_WithSurgeryObservation_UpdatesExistingSurgeryMultiValueObservation_RemovesDuplicate() { // Arrange var patientId = ObjectId.GenerateNewId(); const string surgeryName = "Surgery"; const string duplicateSurgeryValue = "Appendectomy"; var surgeryObservation = new PatientObservation { Name = surgeryName, PatientId = patientId, Value = duplicateSurgeryValue }; const string expectedMultiValueObservationName = $"{surgeryName}_Multivalue"; var existingMultiValueObservation = new PatientObservation { PatientId = patientId, Name = expectedMultiValueObservationName, Value = new[] { "Appendectomy", "Tonsillectomy" }, Time = DateTime.UtcNow.AddMinutes(-30), Expired = false }; // Simulate an existing Surgery_Multivalue observation with a duplicate value _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(expectedMultiValueObservationName)))) .ReturnsAsync([existingMultiValueObservation]); // Act await _calculatedObservations.Map(surgeryObservation); // Assert // Verify that the existing Surgery_Multivalue observation was expired _mockObservationService.Verify( x => x.UpdateObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals(expectedMultiValueObservationName) && o.Expired)), Times.Once); // Verify that a new Surgery_Multivalue observation was inserted with the duplicate removed _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals(expectedMultiValueObservationName) && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 2 && ((string[])o.Value)[1].ToString() == "Appendectomy" && ((string[])o.Value)[0].ToString() == "Tonsillectomy"), true, true), Times.Once); } /// /// Verifies that does not insert or update any observation when a surgery observation is provided with a non-string Value. /// [Test] public async Task Map_WithSurgeryObservation_HandlesNonStringValue() { // Arrange var patientId = ObjectId.GenerateNewId(); const string surgeryName = "Surgery"; var surgeryObservation = new PatientObservation { Name = surgeryName, PatientId = patientId, Value = 123 }; // Non-string value // Act await _calculatedObservations.Map(surgeryObservation); // Assert // Verify that no new observation was inserted _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); // Verify that no existing observation was updated _mockObservationService.Verify( x => x.UpdateObservation(It.IsAny()), Times.Never); } /// /// Verifies that the method, when invoked with a respiratory device multivalue observation /// and no prior observations, inserts a "Complexity" observation with a value of 1. /// [Test] public async Task Map_WithRespiratoryDeviceMultiValueObservation_CallsCalculateComplexity_Return1() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "Respiratory_Device_Multivalue"; var observationValue = new[] { "Oxigeno (O2)/Alto flujo" }; var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; //value 1 _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Intravenous_Routes_Multivalue")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Medication_Multivalue")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("System_Multivalue")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Newborn_Weight")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Surgery_Multivalue")))) .ReturnsAsync([]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 1), true, false), Times.Once); } [Test] public async Task Map_WithIntravenousRoutesAndRespiratoryDeviceMultiValueObservation_CalculatesComplexity_Return5() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "Intravenous_Routes_Multivalue"; var observationValue = new[] { "VV central" }; var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; // value 2 var ventilationObs = new PatientObservation { Name = "Respiratory_Device_Multivalue", PatientId = patientId, Value = new[] { "Ventilación mecánica Invasiva" } }; //value 3 _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([ventilationObs]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Medication_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("System_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Newborn_Weight")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Surgery_Multivalue")))).ReturnsAsync([]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 5), // Esperamos 2 para "VV central" y 3 de "Ventilación mecánica Invasiva" según ComplexityValuesJson true, false), Times.Once); } /// /// Verifies that mapping a patient observation with the "Medication_Multivalue" name containing two /// medication values ("Adrenalina" and "Dopamina") results in a new "Complexity" observation being /// inserted with a calculated integer value of 4, while all related observation lookups (respiratory /// devices, intravenous routes, system, newborn weight, and surgery) return empty results. /// /// The instance passed implicitly to the /// test runner; not directly used as a method argument since this is a parameterless test method. [Test] public async Task Map_WithTwoMedicationMultiValueObservation_CalculatesComplexity_Return4() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "Medication_Multivalue"; var observationValue = new[] { "Adrenalina", "Dopamina" }; var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("System_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Newborn_Weight")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Surgery_Multivalue")))).ReturnsAsync([]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 4), // Esperamos 2 para "Adrenalina" y 2 para Dopamina true, false), Times.Once); } /// /// Verifies that when a patient has a system multivalue observation, medication multivalue observations, and a newborn weight observation, the mapping process calculates a complexity value of 9 and inserts it as a new "Complexity" observation. /// [Test] public async Task Map_WithSystemMedicationAndNewbornWeightMultiValueObservation_CalculatesComplexity_Return9() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "System_Multivalue"; var observationValue = new[] { "Hipotermia" }; var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; //value 2 var medicationObs = new PatientObservation { Name = "Medication_Multivalue", PatientId = patientId, Value = new[] { "Isoprenalina", "Milrinona" } }; //value 1 + 2 var newbornWeight = new PatientObservation { Name = "Newborn_Weight", PatientId = patientId, Value = 800 }; //value 4 _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Medication_Multivalue")))).ReturnsAsync([medicationObs]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Newborn_Weight")))).ReturnsAsync([newbornWeight]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Surgery_Multivalue")))).ReturnsAsync([]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 9), // Esperamos 9 true, false), Times.Once); } [Test] public async Task Map_WithNewbornWeightObservation_CalculatesComplexity_Return4() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "Newborn_Weight"; const string observationValue = "600"; // Ejemplo de peso var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Medication_Multivalue")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("System_Multivalue")))) .ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Surgery_Multivalue")))) .ReturnsAsync([]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 4), // Esperamos 4 para un peso entre 501 y 1000 según ComplexityValuesJson true, false), Times.Once); } /// /// Verifies that the Map method correctly calculates a complexity value of 13 when the input observation represents surgery, medication, and newborn weight data, by aggregating the per-section contribution of each observation type. /// [Test] public async Task Map_WithSurgeryMedicationMewbornWeightMultiValueObservation_CalculatesComplexity_Returns13() { // Arrange var patientId = ObjectId.GenerateNewId(); const string observationName = "Surgery_Multivalue"; var observationValue = new[] { "Cardiaca", "Toracica", "Ortopedia" }; var observation = new PatientObservation { Name = observationName, PatientId = patientId, Value = observationValue }; //value 4 + 3 + 1 var medicationObs = new PatientObservation { Name = "Medication_Multivalue", PatientId = patientId, Value = new[] { "Isoprenalina", "Milrinona" } }; //value 1 + 2 var newbornWeight = new PatientObservation { Name = "Newborn_Weight", PatientId = patientId, Value = 1800 }; //value 2 _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(observationName)))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Respiratory_Device_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Intravenous_Routes_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Medication_Multivalue")))).ReturnsAsync([medicationObs]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("System_Multivalue")))).ReturnsAsync([]); _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains("Newborn_Weight")))).ReturnsAsync([newbornWeight]); // Act await _calculatedObservations.Map(observation); // Assert _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Complexity") && o.Value is int && (int)o.Value == 13), // Esperamos 13 true, false), Times.Once); } [Test] public async Task CalculateSaturation_DiffObservation_WhenPreObservationExistsAndPostIsFound_InsertsDiffAndPrePost() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var preObservation = new PatientObservation { PatientId = patientId, Name = preObservationName, Value = 98, Time = currentTime.AddMinutes(-5) }; var postObservation = new PatientObservation { PatientId = patientId, Name = postObservationName, Value = 95, Time = currentTime }; // Simula que FindLastObservations devuelve la observación post _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([postObservation]); // Act await _calculatedObservations.Map(preObservation); // Assert // Verifica que se insertaron dos observaciones _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Diff" && o.Value.Equals(Math.Round(98.0 - 95.0, 2))), // Verifica la diferencia calculada true, true), Times.Once); _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Pre_Post" && o.Value.Equals("98/95")), true, true), Times.Once); } [Test] public async Task CalculateSaturation_DiffObservation_WhenPostObservationExistsAndPreIsFound_InsertsDiffAndPrePost() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var preObservation = new PatientObservation { PatientId = patientId, Name = preObservationName, Value = 98, Time = currentTime.AddMinutes(-5) }; var postObservation = new PatientObservation { PatientId = patientId, Name = postObservationName, Value = 95, Time = currentTime }; // Simula que FindLastObservations devuelve la observación pre _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([preObservation]); // Act await _calculatedObservations.Map(postObservation); // Assert // Verifica que se insertaron dos observaciones _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Diff" && o.Value.Equals(Math.Round(98.0 - 95.0, 2))), true, true), Times.Once); _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Pre_Post" && o.Value.Equals("98/95")), true, true), Times.Once); } [Test] public async Task CalculateSaturation_DiffObservation_WhenOnlyPreObservationExists_DoesNotInsertNewObservations() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2_Pre"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var preObservation = new PatientObservation { PatientId = patientId, Name = preObservationName, Value = 98, Time = currentTime.AddMinutes(-5) }; // Simula que FindLastObservations devuelve solo la observación pre _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([preObservation]); // Act await _calculatedObservations.Map(preObservation); // Assert // Verifica que no se insertaron nuevas observaciones _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task CalculateSaturation_DiffObservation_WhenOnlyPostObservationExists_DoesNotInsertNewObservations() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2_Pre"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var postObservation = new PatientObservation { PatientId = patientId, Name = postObservationName, Value = 95, Time = currentTime }; // Simula que FindLastObservations devuelve solo la observación post _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([postObservation]); // Act await _calculatedObservations.Map(postObservation); // Assert // Verifica que no se insertaron nuevas observaciones _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task CalculateSaturation_DiffObservation_WithDifferentPrePostValues_CalculatesCorrectDifference() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var preObservation = new PatientObservation { PatientId = patientId, Name = preObservationName, Value = 99.5, Time = currentTime.AddMinutes(-5) }; var postObservation = new PatientObservation { PatientId = patientId, Name = postObservationName, Value = 92.1, Time = currentTime }; // Simula que FindLastObservations devuelve la observación post _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([postObservation]); // Act await _calculatedObservations.Map(preObservation); // Assert // Verifica la diferencia calculada correctamente _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Diff" && o.Value.Equals(7.4)), true, true), Times.Once); _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Pre_Post" && o.Value.Equals("99,5/92,1")), true, true), Times.Once); } [Test] public async Task CalculateSaturation_DiffObservation_WithNonNumericPreValue_TreatsAsZero() { // Arrange var patientId = ObjectId.GenerateNewId(); const string preObservationName = "SpO2"; const string postObservationName = "SpO2_Post"; var currentTime = DateTime.UtcNow; var preObservation = new PatientObservation { PatientId = patientId, Name = preObservationName, Value = "TextoNoNumerico", Time = currentTime.AddMinutes(-5) }; var postObservation = new PatientObservation { PatientId = patientId, Name = postObservationName, Value = "95", Time = currentTime }; // Simula que FindLastObservations devuelve la observación post _mockObservationService.Setup(x => x.FindLastObservations(patientId, 1, It.Is>(list => list.Contains(preObservationName) && list.Contains(postObservationName)))) .ReturnsAsync([postObservation]); // Act await _calculatedObservations.Map(preObservation); // Assert // Verifica que la diferencia se calcula como 0 - 95 = -95 _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Diff" && o.Value.Equals(Math.Round(0 - 95.0, 2))), true, true), Times.Once); _mockObservationService.Verify(x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name == "SpO2_Pre_Post" && o.Value.Equals("TextoNoNumerico/95")), true, true), Times.Once); } /// /// Verifies that mapping a patient treatment with no placer order returns the original treatment unchanged. /// [Test] public async Task Map_TreatmentWithNoPlacerOrder_ReturnsOriginalTreatment() { // Arrange var treatment = new PatientTreatment { PlacerOrder = null }; // Act var result = await _calculatedObservations.Map(treatment); // Assert Assert.That(result, Is.SameAs(treatment)); Assert.That(treatment.PlacerOrder, Is.Null); } /// /// Verifies that mapping a treatment which has active older treatments sets the order control to XO /// (cancel as a result of a new order being accepted) and does not insert a new observation. /// [Test] public async Task Map_TreatmentWithActiveOlderTreatments_SetsOrderControlToXO() { // Arrange var patientId = ObjectId.GenerateNewId(); const string orderIdentifier = "ORD123"; var treatment = new PatientTreatment { PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier } }; var oldTreatments = new List { new() }; _treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments); // Act var result = await _calculatedObservations.Map(treatment); // Assert Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Xo)); _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } /// /// Verifies that when mapping a patient treatment with no active older treatments, the resulting order control is set to and no patient observation is inserted. /// [Test] public async Task Map_TreatmentWithNoActiveOlderTreatments_SetsOrderControlToNW() { // Arrange var patientId = ObjectId.GenerateNewId(); const string orderIdentifier = "ORD123"; var treatment = new PatientTreatment { PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier } }; _treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync([]); // Act var result = await _calculatedObservations.Map(treatment); // Assert Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Nw)); _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } /// /// Verifies that when a patient treatment has an end time set, mapping it sets the order control to and does not insert a new observation. /// [Test] public async Task Map_TreatmentWithEndTimeSet_SetsOrderControlToDC() { // Arrange var patientId = ObjectId.GenerateNewId(); const string orderIdentifier = "ORD123"; var treatment = new PatientTreatment { PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier }, EndTime = DateTime.UtcNow.AddHours(1) }; _treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync([]); // Act var result = await _calculatedObservations.Map(treatment); // Assert Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Dc)); _mockObservationService.Verify( x => x.InsertObservation(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task Map_TreatmentWithEndTimeSet_OverridesOrderControlFromOldTreatments() { // Arrange var patientId = ObjectId.GenerateNewId(); const string orderIdentifier = "ORD123"; var treatment = new PatientTreatment { PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier }, EndTime = DateTime.UtcNow.AddHours(1) }; var oldTreatments = new List { new() }; _treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments); // Act var result = await _calculatedObservations.Map(treatment); // Assert // Aunque había tratamientos antiguos, EndTime debería priorizar OrderControlType.DC Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Dc)); } [Test] public async Task Map_TreatmentWithMedication_InsertObservation() { // Arrange var patientId = ObjectId.GenerateNewId(); const string orderIdentifier = "ORD123"; var code = new Code { Identifier = "16323", CodingSystem = "CCC", Text = "Amiodarona vo" }; var medication = new Medicine { Name = code.Text, Codes = [code.Identifier], Type = ["Medication"], Group = ["Antiarrítmicos"] }; var treatment = new PatientTreatment { PatientId = patientId, PlacerOrder = new Entity { EntityIdentifier = orderIdentifier }, RequestedGiveCodes = [code] }; var oldTreatments = new List { new() }; _treatmentServiceMock.Setup(x => x.GetActiveTreatmentsByPatient(patientId)).ReturnsAsync(oldTreatments); _medicineServiceMock.Setup(m => m.GetByCode(code.Identifier)).ReturnsAsync(medication); _mockObservationService.Setup(s => s.FindLastObservations(It.IsAny(), 1, It.IsAny>())) .ReturnsAsync([]); // Act var result = await _calculatedObservations.Map(treatment); // Assert //Assert.That(result,Is.Null); Assert.That(result.OrderControl, Is.EqualTo(OrderControlType.Xo)); _mockObservationService.Verify( x => x.InsertObservation(It.Is(o => o.PatientId == patientId && o.Name != null && o.Name.Equals("Medication_Multivalue") && o.Value.GetType() == typeof(string[]) && ((string[])o.Value).Length == 1 && ((string[])o.Value)[0].ToString() == "Amiodarona vo" ), true, true), Times.Once); } }