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;
///
/// Test fixture that contains unit tests for the type.
///
///
/// Marked with TestFixture so that the NUnit test runner discovers and executes the contained test methods.
///
///
[TestFixture]
public class CalculatedObservationsTest
{
///
/// Initializes the mocked dependencies and configuration required to instantiate for unit tests, including observation, medicine, and treatment services, the logger, and an populated with mapping interventions and complexity observation values deserialized from JSON.
///
///
[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);
}
///
/// Verifies that when a new "Intervention_In" observation is mapped via Map and the patient's prior "Respiratory_Device_Multivalue" observation is expired (so there is no existing active last observation), a new named "Respiratory_Device_Multivalue" is inserted containing the new intervention while the existing expired observation is left untouched.
///
///
[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);
}
///
/// Verifies that when a new Intervention_In observation is mapped for a patient that already has an
/// active Respiratory_Device_Multivalue observation, the new intervention is appended to the existing
/// multi-value observation via rather than inserted as a
/// new record through .
///
///
[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);
}
///
/// Verifies that the Map method persists a "Complexity" with value 5
/// when an "Intravenous_Routes_Multivalue" entry of "VV central" (contributing 2) and a "Respiratory_Device_Multivalue"
/// entry of "Ventilación mecánica Invasiva" (contributing 3) are provided, summing their mapped complexity contributions.
///
///
[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);
}
///
/// Verifies that values mapped through the calculated observations pipeline
/// produce a Complexity observation with value 4 when a newborn weight observation of 600
/// is provided and no previous observations exist for the respiratory, intravenous, medication, system,
/// or surgery multivalue categories.
///
///
[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);
}
///
/// Tests that inserts a diff observation with the calculated difference and a combined pre/post observation when a pre-observation is provided and the matching post-observation is found through .
///
///
[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);
}
///
/// Verifies that when a post observation is processed and a matching pre observation is found, both a diff observation (with the computed difference value) and a combined pre/post observation (with the pre and post values) are inserted.
///
///
[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);
}
///
/// Verifies that does not insert new records when only the pre-observation is available for the patient and no matching post-observation is returned by .
///
///
[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);
}
///
/// Verifies that CalculateSaturation for a diff observation does not insert new
/// entries when only the post-observation is found and the
/// pre-observation is missing, ensuring no fallback insert occurs in this scenario.
///
///
[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);
}
///
/// Verifies that the saturation difference calculation correctly handles pre and post values that differ, producing a "SpO2_Diff" observation with the numeric difference (7.4) and a "SpO2_Pre_Post" observation with both values formatted as "99,5/92,1".
///
///
[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);
}
///
/// Verifies that when mapping a pre-observation whose is non-numeric, the
/// CalculateSaturation logic treats the pre-value as 0 when computing the difference against the latest
/// matching post-observation returned by .
/// Confirms that a SpO2_Diff observation is inserted with the value 0 - post rounded to two decimals,
/// and a SpO2_Pre_Post observation is inserted concatenating the raw pre-value and post-value.
///
///
[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);
}
///
/// Verifies that mapping a whose is set yields a result with , overriding the order control that would otherwise be derived from the patient's previously active treatments.
///
/// A that completes when the assertions have been evaluated.
///
[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));
}
///
/// Verifies that the map operation inserts an observation when the supplied carries a medication code. The test arranges a treatment with a single requested give code, configures the treatment, medicine, and observation services to return an existing active treatment list, the matching , and no previous observations; then asserts that the resulting is and that the observation service is invoked once with a whose name equals "Medication_Multivalue" and whose value is a array of length one containing the medication text.
///
///
[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);
}
}