using System.Net; using System.Net.Http.Json; using System.Text.Json; using HrynCo.NotificationService.DAL.Abstract.Providers; using HrynCo.NotificationService.DAL.Abstract.Repositories; using HrynCo.NotificationService.DAL.Abstract.Templates; using Microsoft.Extensions.DependencyInjection; namespace HrynCo.NotificationService.Web.IntegrationTests; public sealed class EmailChannelServiceLinkTests(TemplateDatabaseFixture fixture) : IClassFixture { [Fact] public async Task RenameUpdatesAllReadPathsAndResolvesChannelsByCurrentName() { await using var context = await DefinitionApiTestContext.CreateAsync(fixture); var channel = await SeedAsync(context); using (var scope = context.App.Services.CreateScope()) { var services = scope.ServiceProvider.GetRequiredService(); var service = (await services.GetAsync(context.ServiceId))!; service.Name = "Invemory-Renamed"; await services.SaveAsync(service, false); } var read = (await context.Client.GetFromJsonAsync($"/api/v1/email-channels/{channel.Id}")).GetProperty("data"); Assert.Equal(context.ServiceId, read.GetProperty("serviceId").GetGuid()); Assert.Equal("Invemory-Renamed", read.GetProperty("serviceName").GetString()); var current = await context.Client.GetFromJsonAsync("/api/v1/email-channels?serviceName=Invemory-Renamed"); Assert.Single(current.GetProperty("data").EnumerateArray()); var previous = await context.Client.GetFromJsonAsync("/api/v1/email-channels?serviceName=TestService"); Assert.Empty(previous.GetProperty("data").EnumerateArray()); Assert.Contains("Invemory-Renamed", await context.Client.GetStringAsync("/admin/channels")); Assert.Contains("Invemory-Renamed", await context.Client.GetStringAsync($"/admin/channels/{channel.Id}")); } [Fact] public async Task EditorAllowsReassignmentWithoutReplacingPasswordOrUsage() { await using var context = await DefinitionApiTestContext.CreateAsync(fixture); var channel = await SeedAsync(context); using var scope = context.App.Services.CreateScope(); var destination = new NotificationServiceInfo { Name = "Invemory-Other" }; await scope.ServiceProvider.GetRequiredService().SaveAsync(destination, true); using var client = context.App.CreateClient(new() { AllowAutoRedirect = false }); var html = await client.GetStringAsync($"/admin/channels/{channel.Id}"); Assert.Contains("(); var saved = (await channels.GetByIdAsync(channel.Id))!; Assert.Equal(destination.Id, saved.ServiceId); Assert.Equal("Invemory-Other", saved.ServiceName); Assert.Equal("test-only-password", Assert.IsType(saved.Settings).Password); Assert.Equal(25, saved.DailyLimit); Assert.Equal(250, saved.MonthlyLimit); Assert.Equal(2, saved.Priority); var summary = Assert.Single(await channels.GetAllWithUsageSummaryAsync(DateOnly.FromDateTime(DateTime.UtcNow))); Assert.Equal(1, summary.DailySent); Assert.Empty(await channels.GetByServiceAsync(context.ServiceId)); Assert.Single(await channels.GetByServiceAsync(destination.Id)); } [Theory] [InlineData(false)] [InlineData(true)] public async Task UpdateRejectsMissingServiceWithoutChangingChannel(bool empty) { await using var context = await DefinitionApiTestContext.CreateAsync(fixture); var channel = await SeedAsync(context); var response = await context.Client.PutAsJsonAsync($"/api/v1/email-channels/{channel.Id}", new { serviceId = empty ? Guid.Empty : Guid.NewGuid(), priority = 9, settings = (SmtpChannelSettings)channel.Settings, dailyLimit = 1, monthlyLimit = 2, warnThresholdPercent = 80, isActive = false }); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); var result = await response.Content.ReadFromJsonAsync(); Assert.Equal("Select an existing service.", result.GetProperty("error").GetProperty("message").GetString()); using var scope = context.App.Services.CreateScope(); var saved = (await scope.ServiceProvider.GetRequiredService().GetByIdAsync(channel.Id))!; Assert.Equal(context.ServiceId, saved.ServiceId); Assert.Equal(2, saved.Priority); Assert.Equal(25, saved.DailyLimit); } private static async Task SeedAsync(DefinitionApiTestContext context) { using var scope = context.App.Services.CreateScope(); var channel = new EmailChannel { ServiceId = context.ServiceId, Priority = 2, EmailChannelType = EmailChannelType.Smtp, DailyLimit = 25, MonthlyLimit = 250, IsActive = true, Settings = new SmtpChannelSettings { Host = "smtp.invalid", Port = 587, Username = "test-user", Password = "test-only-password", UseSsl = true, FromEmail = "sender@example.invalid", FromName = "Invemory Test" } }; await scope.ServiceProvider.GetRequiredService().AddAsync(channel); await scope.ServiceProvider.GetRequiredService() .IncrementUsageAsync(channel.Id, DateOnly.FromDateTime(DateTime.UtcNow)); return channel; } }