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 PumpAlarmStateRepositoryTest { private PumpAlarmStateRepository _repo; private IOptions _apiSettings; private static readonly DateTime Now = DateTime.UtcNow; private const string DeviceA = "Device-A"; private const string DeviceB = "Device-B"; private static readonly ObjectId PatientId = ObjectId.GenerateNewId(); // ------------------------------------------------------------------- // INIT: preparar colección, índices y datos iniciales // ------------------------------------------------------------------- /// /// One-time setup that prepares the integration test environment for . /// Configures the API settings, drops and recreates the "pump_alarm_state" collection, instantiates the repository with its indexes, and seeds three initial alarm state records across two devices, verifying the seeded count. /// [OneTimeSetUp] public async Task Init() { _apiSettings = Options.Create(new ApiSettings { PumpAlarmState = "pump_alarm_state" }); await IntegrationDb.Database.DropCollectionAsync("pump_alarm_state"); await IntegrationDb.Database.CreateCollectionAsync("pump_alarm_state"); _repo = new PumpAlarmStateRepository( _apiSettings, IntegrationDb.Database ); await _repo.CreateIndexes(); // datos iniciales var initial = new List { new() { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Attention, AlarmCodeMdc = "AC001", LastUpdated = Now.AddSeconds(-3) }, new() { Id = ObjectId.GenerateNewId(), DeviceId = DeviceA, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = "AC002", LastUpdated = Now.AddSeconds(-1) }, new() { Id = ObjectId.GenerateNewId(), DeviceId = DeviceB, PatientId = PatientId, AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = "AC003", LastUpdated = Now.AddSeconds(-2) } }; await _repo.Collection.InsertManyAsync(initial); var count = await _repo.Collection.CountDocumentsAsync(_ => true); Assert.That(count, Is.EqualTo(3)); } // ------------------------------------------------------------------- // FIND ACTIVE // ------------------------------------------------------------------- /// /// Verifies that FindActiveAsync returns the correct active alarm matching the specified device identifier, alarm type, and alarm code. /// [Test] public async Task FindActiveAsync_ReturnsCorrectAlarm() { var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "AC002"); using (Assert.EnterMultipleScope()) { Assert.That(alarm, Is.Not.Null); Assert.That(alarm!.DeviceId, Is.EqualTo(DeviceA)); Assert.That(alarm.AlarmType, Is.EqualTo(PumpEnum.AlarmType.Occlusion)); Assert.That(alarm.AlarmCodeMdc, Is.EqualTo("AC002")); } } /// /// Verifies that FindActiveAsync returns null when no active alarm matching the specified device, alarm type, and identifier exists. /// [Test] public async Task FindActiveAsync_ReturnsNull_WhenNotFound() { var alarm = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "XXX"); Assert.That(alarm, Is.Null); } // ------------------------------------------------------------------- // UPSERT ACTIVE // ------------------------------------------------------------------- /// /// Verifies that UpsertActiveAsync correctly inserts a new active pump alarm into the repository /// when no existing alarm with the same device, type, and code is found, and that the inserted alarm /// can subsequently be retrieved via FindActiveAsync. /// [Test] public async Task UpsertActiveAsync_InsertsNew() { var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-C", AlarmType = PumpEnum.AlarmType.Attention, AlarmCodeMdc = "NEW", PatientId = PatientId, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); var found = await _repo.FindActiveAsync("Device-C", PumpEnum.AlarmType.Attention, "NEW"); Assert.That(found, Is.Not.Null); } [Test] public async Task UpsertActiveAsync_UpdatesExisting() { var updated = new PumpAlarmState { Id = ObjectId.GenerateNewId(), // será ignorado por replace DeviceId = DeviceA, AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = "AC002", PatientId = PatientId, LastUpdated = Now.AddMinutes(1) }; await _repo.UpsertActiveAsync(updated); var found = await _repo.FindActiveAsync(DeviceA, PumpEnum.AlarmType.Occlusion, "AC002"); Assert.That(found, Is.Not.Null); Assert.That(found!.LastUpdated, Is.EqualTo(updated.LastUpdated).Within(TimeSpan.FromMilliseconds(2))); } // ------------------------------------------------------------------- // REMOVE ACTIVE ALARM // ------------------------------------------------------------------- /// /// Verifies that RemoveAsync correctly deletes an active alarm by device, alarm type, and alarm code, and that a subsequent lookup returns no result. /// [Test] public async Task RemoveAsync_Works() { var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-D", AlarmType = PumpEnum.AlarmType.Attention, AlarmCodeMdc = "D1", PatientId = PatientId, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); await _repo.RemoveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1"); var found = await _repo.FindActiveAsync("Device-D", PumpEnum.AlarmType.Attention, "D1"); Assert.That(found, Is.Null); } // ------------------------------------------------------------------- // DELETE BY PATIENT ID // ------------------------------------------------------------------- /// /// Verifies that the repository's DeleteByPatientId method successfully removes a previously upserted /// for the specified patient, ensuring no matching records remain in the collection. /// [Test] public async Task DeleteByPatientId_Works() { var pid = ObjectId.GenerateNewId(); var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-E", AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = "DDD", PatientId = pid, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); await _repo.DeleteByPatientId(pid); var list = await _repo.Collection.FindAsync(x => x.PatientId == pid); Assert.That(await list.AnyAsync(), Is.False); } // ------------------------------------------------------------------- // FIND ALL ACTIVE BY DEVICE // ------------------------------------------------------------------- /// /// Verifies that FindAllActiveByDeviceAsync returns only active pump alarm states that belong to the specified device. /// [Test] public async Task FindAllActiveByDeviceAsync_ReturnsCorrect() { var result = await _repo.FindAllActiveByDeviceAsync(DeviceA); var pumpAlarmStates = result.ToList(); Assert.That(pumpAlarmStates, Is.Not.Empty); Assert.That(pumpAlarmStates.All(x => x.DeviceId == DeviceA), Is.True); } // ------------------------------------------------------------------- // UPDATE MANY BY FIELD // ------------------------------------------------------------------- /// /// Verifies that UpdateManyObjectIdByFieldNameAsync successfully updates the PatientId field /// from the old ObjectId to a new ObjectId for matching documents, returning the expected count of /// updated records and making the document retrievable by the new ObjectId. /// [Test] public async Task UpdateManyObjectIdByFieldNameAsync_Works() { var oldId = ObjectId.GenerateNewId(); var newId = ObjectId.GenerateNewId(); // Insert one alarm to update var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-F", AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = "FFF", PatientId = oldId, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); var updated = await _repo.UpdateManyObjectIdByFieldNameAsync("PatientId", newId, oldId); using (Assert.EnterMultipleScope()) { Assert.That(updated, Is.EqualTo(1)); var found = await _repo.Collection.FindAsync(x => x.PatientId == newId); Assert.That(await found.AnyAsync(), Is.True); } } [Test] public async Task UpsertActiveAsync_NoDuplicateOnRepeatedCalls() { var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-Repeat", AlarmType = PumpEnum.AlarmType.Attention, AlarmCodeMdc = "R1", PatientId = PatientId, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); await _repo.UpsertActiveAsync(alarm); // segunda llamada idéntica var alarmsEnum = await _repo.FindAllActiveByDeviceAsync("Device-Repeat"); var list = alarmsEnum.ToList(); Assert.That(list, Has.Count.EqualTo(1)); } /// /// Verifies that UpsertActiveAsync correctly inserts a PumpAlarmState record when the AlarmCodeMdc is null, and that the record can be retrieved via FindActiveAsync using a null alarm code. /// [Test] public async Task UpsertActiveAsync_InsertsWhenAlarmCodeIsNull() { var alarm = new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-NullCode", AlarmType = PumpEnum.AlarmType.Occlusion, AlarmCodeMdc = null, PatientId = PatientId, LastUpdated = Now }; await _repo.UpsertActiveAsync(alarm); var found = await _repo.FindActiveAsync("Device-NullCode", PumpEnum.AlarmType.Occlusion, null); Assert.That(found, Is.Not.Null); Assert.That(found!.AlarmCodeMdc, Is.Null); } /// /// Verifies that RemoveAsync removes every active alarm matching the specified device identifier and alarm type, not just a single record. /// [Test] public async Task RemoveAsync_RemovesAllMatching() { var alarms = new[] { new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-Multi", AlarmType = PumpEnum.AlarmType.AirInLine, AlarmCodeMdc = "XX1", PatientId = PatientId, LastUpdated = Now }, new PumpAlarmState { Id = ObjectId.GenerateNewId(), DeviceId = "Device-Multi", AlarmType = PumpEnum.AlarmType.AirInLine, AlarmCodeMdc = "XX2", PatientId = PatientId, LastUpdated = Now } }; foreach (var a in alarms) await _repo.UpsertActiveAsync(a); await _repo.RemoveAsync("Device-Multi", PumpEnum.AlarmType.AirInLine); var remaining = await _repo.FindAllActiveByDeviceAsync("Device-Multi"); Assert.That(remaining, Is.Empty); } }