using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Moq; using PowderCoating.Application.Interfaces; using PowderCoating.Core.Entities; using PowderCoating.Core.Enums; using PowderCoating.Infrastructure.Data; using PowderCoating.Shared.Constants; using PowderCoating.Web.Controllers; namespace PowderCoating.UnitTests; public class EmailBroadcastControllerTests { [Fact] public async Task Preview_RendersMergedSampleAndSanitizesHtml() { await using var context = CreateContext(); context.Companies.Add(new Company { Id = 7, CompanyId = 7, CompanyName = "River City Powder", PrimaryContactName = "Jamie Rivera", PrimaryContactEmail = "jamie@example.com", IsActive = true }); context.Users.Add(new ApplicationUser { Id = "admin-7", CompanyId = 7, CompanyRole = AppConstants.CompanyRoles.CompanyAdmin, FirstName = "Alex", LastName = "Admin", Email = "alex@example.com", UserName = "alex@example.com", IsActive = true }); await context.SaveChangesAsync(); var controller = CreateController(context); var result = await controller.Preview(new AdminEmailSelectionModel { Subject = "Update for {{CompanyName}}", BodyHtml = "

Hi {{FirstName}}, contact {{CompanyAdminName}} at {{CompanyAdminEmail}}.

", CompanyIds = [7] }); var view = Assert.IsType(result); var model = Assert.IsType(view.Model); Assert.Equal("Update for River City Powder", model.SamplePreview.RenderedSubject); Assert.Contains("Hi Jamie", model.SamplePreview.RenderedHtmlBody); Assert.Contains("Alex Admin", model.SamplePreview.RenderedHtmlBody); Assert.Contains("alex@example.com", model.SamplePreview.RenderedHtmlBody); Assert.DoesNotContain("(); emailService .Setup(x => x.SendEmailAsync( "morgan@example.com", "Morgan Lee", "Notice for Summit Coatings", It.IsAny(), It.IsAny(), null, null, null, "admin-notify@example.com", "Powder Coating Logix Admin")) .ReturnsAsync((true, (string?)null)); var platformSettings = new Mock(); platformSettings .Setup(x => x.GetAsync(PlatformSettingKeys.AdminNotificationEmail)) .ReturnsAsync("admin-notify@example.com,backup@example.com"); var controller = CreateController(context, emailService, platformSettings); var result = await controller.Send(new AdminEmailSendRequest { Subject = "Notice for {{CompanyName}}", BodyHtml = "

Hello {{FirstName}},

Thanks for using {{CompanyName}}.

", CompanyIds = [11] }); var redirect = Assert.IsType(result); Assert.Equal("Index", redirect.ActionName); var log = await context.NotificationLogs.IgnoreQueryFilters().SingleAsync(); Assert.Equal(NotificationType.AdminEmail, log.NotificationType); Assert.Equal(NotificationStatus.Sent, log.Status); Assert.Equal("morgan@example.com", log.Recipient); Assert.Equal("Notice for Summit Coatings", log.Subject); Assert.Contains("Hello Morgan", log.Message); emailService.VerifyAll(); } [Fact] public async Task Send_WhenPrimaryContactEmailMissing_WritesSkippedLogWithoutSending() { await using var context = CreateContext(); context.Companies.Add(new Company { Id = 13, CompanyId = 13, CompanyName = "No Inbox Inc", PrimaryContactName = "Taylor Noemail", PrimaryContactEmail = string.Empty, IsActive = true }); await context.SaveChangesAsync(); var emailService = new Mock(); var controller = CreateController(context, emailService); var result = await controller.Send(new AdminEmailSendRequest { Subject = "Heads up for {{CompanyName}}", BodyHtml = "

Hello {{FirstName}}

", CompanyIds = [13] }); var redirect = Assert.IsType(result); Assert.Equal("Index", redirect.ActionName); var log = await context.NotificationLogs.IgnoreQueryFilters().SingleAsync(); Assert.Equal(NotificationType.AdminEmail, log.NotificationType); Assert.Equal(NotificationStatus.Skipped, log.Status); Assert.Equal(string.Empty, log.Recipient); Assert.Equal("Company primary contact email is not configured.", log.ErrorMessage); emailService.Verify( x => x.SendEmailAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } private static EmailBroadcastController CreateController( ApplicationDbContext context, Mock? emailService = null, Mock? platformSettings = null) { var controller = new EmailBroadcastController( context, (emailService ?? new Mock()).Object, (platformSettings ?? CreatePlatformSettings()).Object, Mock.Of>()); var httpContext = new DefaultHttpContext(); controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; controller.TempData = new TempDataDictionary(httpContext, Mock.Of()); return controller; } private static Mock CreatePlatformSettings() { var settings = new Mock(); settings.Setup(x => x.GetAsync(It.IsAny())).ReturnsAsync((string?)null); return settings; } private static ApplicationDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } }