using ERPCore.Domain.Entities; using ERPCore.Domain.Notifications; using ERPCore.Repositories; using ERPCore.Services; using ERPCore.System.Errors; using ERPCore.Tests.TestSupport; using Microsoft.EntityFrameworkCore; namespace ERPCore.Tests; public class NotificationConfigServiceTests { [Fact] public async Task GetAsync_MergesSavedValuesWithDiscoveredModules() { var dbName = Guid.NewGuid().ToString("N"); await using var db = NotificationConfigTestSupport.CreateContext(dbName); await NotificationConfigTestSupport.SeedAsync(db, new[] { new NotificationConfigModule { ModuleKey = "sale.create", EmailEnabled = true, SmsEnabled = false, InAppEnabled = true } }); var service = CreateService(db); var result = await service.GetAsync(); Assert.Equal(7u, result.RowVersion); Assert.Contains(result.Value.Modules, m => m.ModuleKey == "sale.create" && m.EmailEnabled && !m.SmsEnabled && m.InAppEnabled); Assert.Contains(result.Value.Modules, m => m.ModuleKey == "grn.confirmed" && !m.EmailEnabled && !m.SmsEnabled && !m.InAppEnabled); } [Fact] public async Task UpdateAsync_PersistsEmptyAndMultiChannelSelections() { var dbName = Guid.NewGuid().ToString("N"); await using var db = NotificationConfigTestSupport.CreateContext(dbName); await NotificationConfigTestSupport.SeedAsync(db); var service = CreateService(db); var catalog = new NotificationModuleCatalog(); var request = new ERPCore.Dtos.Notifications.UpdateNotificationConfigRequest { Modules = catalog.GetAll().Select((module, index) => new ERPCore.Dtos.Notifications.UpdateNotificationModuleRequest { ModuleKey = module.Key, EmailEnabled = index == 0, SmsEnabled = index == 1, InAppEnabled = index == 1 }).ToList() }; var updated = await service.UpdateAsync(request, 7); Assert.Equal(7u, updated.RowVersion); Assert.Contains(updated.Value.Modules, m => m.ModuleKey == catalog.GetAll()[0].Key && m.EmailEnabled && !m.SmsEnabled && !m.InAppEnabled); Assert.Contains(updated.Value.Modules, m => m.ModuleKey == catalog.GetAll()[1].Key && !m.EmailEnabled && m.SmsEnabled && m.InAppEnabled); await using var verifyDb = NotificationConfigTestSupport.CreateContext(dbName); var persisted = await verifyDb.NotificationConfigModules.AsNoTracking().ToListAsync(); Assert.Contains(persisted, m => m.ModuleKey == catalog.GetAll()[0].Key && m.EmailEnabled && !m.SmsEnabled && !m.InAppEnabled); Assert.Contains(persisted, m => m.ModuleKey == catalog.GetAll()[1].Key && !m.EmailEnabled && m.SmsEnabled && m.InAppEnabled); } [Fact] public async Task ResolveEnabledChannelsAsync_ReturnsEmptyWhenNothingEnabled() { var dbName = Guid.NewGuid().ToString("N"); await using var db = NotificationConfigTestSupport.CreateContext(dbName); await NotificationConfigTestSupport.SeedAsync(db, new[] { new NotificationConfigModule { ModuleKey = "sale.create", EmailEnabled = false, SmsEnabled = false, InAppEnabled = false } }); var service = CreateService(db); var channels = await service.ResolveEnabledChannelsAsync("sale.create"); Assert.Empty(channels); } [Fact] public async Task ResolveEnabledChannelsAsync_ReturnsMultipleChannels() { var dbName = Guid.NewGuid().ToString("N"); await using var db = NotificationConfigTestSupport.CreateContext(dbName); await NotificationConfigTestSupport.SeedAsync(db, new[] { new NotificationConfigModule { ModuleKey = "sale.create", EmailEnabled = true, SmsEnabled = true, InAppEnabled = false } }); var service = CreateService(db); var channels = await service.ResolveEnabledChannelsAsync("sale.create"); Assert.Equal(new[] { NotificationChannel.Email, NotificationChannel.Sms }, channels); } [Fact] public async Task UpdateAsync_MapsConcurrencyFailuresToDomainException() { var dbName = Guid.NewGuid().ToString("N"); await using var db = NotificationConfigTestSupport.CreateContext(dbName); await NotificationConfigTestSupport.SeedAsync(db); var service = CreateService(db, new ThrowingUnitOfWork()); var catalog = new NotificationModuleCatalog(); var request = new ERPCore.Dtos.Notifications.UpdateNotificationConfigRequest { Modules = catalog.GetAll().Select(module => new ERPCore.Dtos.Notifications.UpdateNotificationModuleRequest { ModuleKey = module.Key, EmailEnabled = false, SmsEnabled = false, InAppEnabled = false }).ToList() }; var ex = await Assert.ThrowsAsync(() => service.UpdateAsync(request, 7)); Assert.Equal(ErrorCodes.ConcurrencyConflict, ex.Code); Assert.Equal(412, ex.StatusCode); } private static NotificationConfigService CreateService(ERPCore.Infra.Persistence.ErpDbContext db, ERPCore.Infra.UoW.IUnitOfWork? uow = null) { var configRepo = new Repository(db); var moduleRepo = new Repository(db); return new NotificationConfigService( configRepo, moduleRepo, new NotificationModuleCatalog(), new TestCurrentUser(), uow ?? new ERPCore.Infra.UoW.UnitOfWork(db)); } }