using adas_core.Domain.Enums; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.Pumps; using adas_core.Infrastructure.Repositories; using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; namespace adas_core.Test.Repositories; [TestFixture] [Category("Integration")] public class PumpObservationRepositoryTest { private PumpObservationRepository _repo; private IOptions _apiSettings; private static readonly DateTime Now = DateTime.UtcNow; private static readonly ObjectId PatientId = ObjectId.GenerateNewId(); // ------------------------------------------------------------------- // INIT – SETUP DE LA COLECCIÓN CON DATOS DE PRUEBA // ------------------------------------------------------------------- [OneTimeSetUp] public async Task Init() { _apiSettings = Options.Create(new ApiSettings { PumpObservations = "pump_observations" }); await IntegrationDb.Database.DropCollectionAsync("pump_observations"); await IntegrationDb.Database.CreateCollectionAsync("pump_observations"); _repo = new PumpObservationRepository( _apiSettings, IntegrationDb.Database ); await _repo.CreateIndexes(); var samples = new List { new() { Id = ObjectId.GenerateNewId(), PatientId = PatientId, DeviceId = "Device-A", Name = "PumpX", Time = Now.AddSeconds(-1), MessageType = PumpEnum.PumpMessageType.Observation }, new() { Id = ObjectId.GenerateNewId(), PatientId = PatientId, DeviceId = "Device-A", Name = "PumpY", Time = Now.AddSeconds(-2), MessageType = PumpEnum.PumpMessageType.Observation }, new() { Id = ObjectId.GenerateNewId(), PatientId = PatientId, DeviceId = "Device-A", Name = "PumpX", Time = Now.AddSeconds(-3), MessageType = PumpEnum.PumpMessageType.Observation } }; await _repo.InsertManyAsync(samples); var count = await _repo.Collection.CountDocumentsAsync(_ => true); Assert.That(count, Is.EqualTo(3)); } // ------------------------------------------------------------------- // FIND LAST OBSERVATIONS (LÍMITE = 2) // ------------------------------------------------------------------- [Test] public async Task FindLastObservations_ReturnsTwo() { var list = await _repo.FindLastObservations(PatientId, "PumpX"); Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(2)); Assert.That(list[0].Time, Is.GreaterThanOrEqualTo(list[1].Time)); } // ------------------------------------------------------------------- // INSERT // ------------------------------------------------------------------- [Test] public async Task InsertAsync_Works() { var pump = new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = ObjectId.GenerateNewId(), DeviceId = "Device-B", Time = Now }; await _repo.InsertAsync(pump); var found = await _repo.Collection.FindAsync(x => x.Id == pump.Id); Assert.That(found.FirstOrDefault(), Is.Not.Null); } [Test] public async Task InsertManyAsync_Works() { var list = new List { new() { Id = ObjectId.GenerateNewId(), DeviceId="D", Time=Now }, new() { Id = ObjectId.GenerateNewId(), DeviceId="D", Time=Now } }; await _repo.InsertManyAsync(list); var count = await _repo.Collection.CountDocumentsAsync(x => list.Select(y => y.Id).Contains(x.Id)); Assert.That(count, Is.EqualTo(2)); } // ------------------------------------------------------------------- // FIND METHODS // ------------------------------------------------------------------- [Test] public async Task FindByDeviceIdAsync_ReturnsOrdered() { var result = await _repo.FindByDeviceIdAsync("Device-A"); var pumpObservations = result.ToList(); using (Assert.EnterMultipleScope()) { Assert.That(pumpObservations, Is.Not.Empty); Assert.That(pumpObservations.First().Time, Is.GreaterThanOrEqualTo(pumpObservations.Last().Time)); } } [Test] public async Task FindByPatientAsync_ReturnsOrdered() { var result = await _repo.FindByPatientAsync(PatientId); var pumpObservations = result.ToList(); using (Assert.EnterMultipleScope()) { Assert.That(pumpObservations, Is.Not.Empty); Assert.That(pumpObservations.First().Time, Is.GreaterThanOrEqualTo(pumpObservations.Last().Time)); } } [Test] public async Task FindLastByDeviceIdAsync_Works() { var obs = await _repo.FindLastByDeviceIdAsync("Device-A"); Assert.That(obs, Is.Not.Null); Assert.That(obs.DeviceId, Is.EqualTo("Device-A")); } [Test] public async Task FindByPatientId_Works() { var list = await _repo.FindByPatientId(PatientId); Assert.That(list.Any(), Is.True); } // ------------------------------------------------------------------- // AGGREGATED LAST OBSERVATIONS // ------------------------------------------------------------------- [Test] public async Task AggregatedPatientLastObservations_DistinctByName() { var result = await _repo.AggregatedPatientLastObservations(PatientId); using (Assert.EnterMultipleScope()) { Assert.That(result, Is.Not.Empty); Assert.That(result, Has.Count.LessThanOrEqualTo(2)); } } // ------------------------------------------------------------------- // DELETE METHODS // ------------------------------------------------------------------- [Test] public async Task DeleteByPatientId_Works() { var pid = ObjectId.GenerateNewId(); await _repo.InsertAsync(new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = pid, DeviceId = "Z", Time = Now }); await _repo.DeleteByPatientId(pid); var list = await _repo.FindByPatientId(pid); Assert.That(list.Any(), Is.False); } [Test] public async Task DeleteOlderThanDaysAsync_Works() { var pid = ObjectId.GenerateNewId(); await _repo.InsertAsync(new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = pid, Name = "TestOld", Time = Now.AddDays(-10) }); var deleted = await _repo.DeleteOlderThanDaysAsync(5); Assert.That(deleted, Is.GreaterThanOrEqualTo(1)); } [Test] public async Task DeleteOlderNumberAsync_Works() { const string name = "HistoryPump"; var obs = Enumerable.Range(0, 5).Select(i => new PumpObservation { Id = ObjectId.GenerateNewId(), DeviceId = "H", Name = name, Time = Now.AddSeconds(-i) }); await _repo.InsertManyAsync(obs); var deleted = await _repo.DeleteOlderNumberAsync(name, 2); Assert.That(deleted, Is.EqualTo(3)); } [Test] public async Task DeleteKeepLastNAsync_Works() { var items = Enumerable.Range(0, 8).Select(i => new PumpObservation { Id = ObjectId.GenerateNewId(), DeviceId = "Device-Clean", Time = Now.AddSeconds(-i) }); await _repo.InsertManyAsync(items); var deleted = await _repo.DeleteKeepLastNAsync(3); Assert.That(deleted, Is.EqualTo(5)); } // ------------------------------------------------------------------- // UPDATE METHOD // ------------------------------------------------------------------- [Test] public async Task UpdateManyObjectIdByFieldAsync_Works() { var oldId = ObjectId.GenerateNewId(); var newId = ObjectId.GenerateNewId(); await _repo.InsertAsync(new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = oldId, DeviceId = "UpdateTest", Time = Now }); var updated = await _repo.UpdateManyObjectIdByFieldAsync("PatientId", newId, oldId); Assert.That(updated, Is.EqualTo(1)); var found = await _repo.FindByPatientId(newId); Assert.That(found.Any(), Is.True); } // ------------------------------------------------------------------- // AGGREGATION: LAST OBSERVATION TIME PER PATIENT // ------------------------------------------------------------------- [Test] public async Task FindAllLastPatientObservationTimeAsync_Works() { var dict = await _repo.FindAllLastPatientObservationTimeAsync(); Assert.That(dict, Is.Not.Null); using (Assert.EnterMultipleScope()) { Assert.That(dict.ContainsKey(PatientId), Is.True); Assert.That(dict[PatientId], Is.LessThanOrEqualTo(DateTime.UtcNow)); } } [Test] public async Task FindByDeviceIdAsync_EmptyWhenOutOfDateRange() { var from = Now.AddYears(-1); var to = Now.AddYears(-1).AddHours(1); var result = await _repo.FindByDeviceIdAsync("Device-A", from, to); Assert.That(result, Is.Empty); } [Test] public async Task FindByPatientAsync_RespectsLimit() { var result = await _repo.FindByPatientAsync(PatientId, limit: 1); var list = result.ToList(); Assert.That(list, Has.Count.EqualTo(1)); } [Test] public async Task FindLastByDeviceIdAsync_ReturnsNullWhenNotExists() { var obs = await _repo.FindLastByDeviceIdAsync("Device-DoesNotExist"); Assert.That(obs, Is.Null); } [Test] public async Task InsertManyAsync_IgnoresEmptyList() { var empty = new List(); Func act = () => _repo.InsertManyAsync(empty); Assert.That(act, Throws.Nothing); } [Test] public async Task DeleteOlderNumberAsync_DoesNothingWhenCountBelowLimit() { const string name = "LimitTestPump"; var obs = new PumpObservation { Id = ObjectId.GenerateNewId(), DeviceId = "Device-X", Name = name, Time = Now }; await _repo.InsertAsync(obs); var deleted = await _repo.DeleteOlderNumberAsync(name, maxCount: 5); Assert.That(deleted, Is.Zero); } [Test] public async Task DeleteOlderThanDaysAsync_DoesNotDeleteRecentObservations() { var obs = new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = PatientId, DeviceId = "Device-Recent", Name = "RecentPump", Time = Now.AddMinutes(-1) // reciente }; await _repo.InsertAsync(obs); var deleted = await _repo.DeleteOlderThanDaysAsync(10); Assert.That(deleted, Is.Zero); } [Test] public async Task AggregatedPatientLastObservations_RemovesDuplicatesByCodeAndName() { var patient = ObjectId.GenerateNewId(); var p1 = new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = patient, DeviceId = "DevA", Code = "C1", Name = "PumpA", Time = Now }; var p2 = new PumpObservation { Id = ObjectId.GenerateNewId(), PatientId = patient, DeviceId = "DevA", Code = "C1", Name = "PumpA", Time = Now.AddSeconds(-1) }; await _repo.InsertManyAsync([p1, p2]); var result = await _repo.AggregatedPatientLastObservations(patient); Assert.That(result, Has.Count.EqualTo(1)); } }