1631786ce2
Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation. Ref: IT-1074
113 lines
6.2 KiB
C#
113 lines
6.2 KiB
C#
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<TemplateDatabaseFixture>
|
|
{
|
|
[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<INotificationServiceRepository>();
|
|
var service = (await services.GetAsync(context.ServiceId))!;
|
|
service.Name = "Invemory-Renamed";
|
|
await services.SaveAsync(service, false);
|
|
}
|
|
var read = (await context.Client.GetFromJsonAsync<JsonElement>($"/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<JsonElement>("/api/v1/email-channels?serviceName=Invemory-Renamed");
|
|
Assert.Single(current.GetProperty("data").EnumerateArray());
|
|
var previous = await context.Client.GetFromJsonAsync<JsonElement>("/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<INotificationServiceRepository>().SaveAsync(destination, true);
|
|
using var client = context.App.CreateClient(new() { AllowAutoRedirect = false });
|
|
var html = await client.GetStringAsync($"/admin/channels/{channel.Id}");
|
|
Assert.Contains("<select", html);
|
|
Assert.Contains("name=\"ServiceId\"", html);
|
|
Assert.Contains("Invemory-Other", html);
|
|
Assert.DoesNotContain("name=\"ServiceName\"", html);
|
|
var fields = TemplateEditorTestFields.Read(html);
|
|
fields["ServiceId"] = destination.Id.ToString();
|
|
fields["Password"] = "";
|
|
fields["UseSsl"] = "true";
|
|
fields["IsActive"] = "true";
|
|
var response = await client.PostAsync("/admin/channels/save", new FormUrlEncodedContent(fields));
|
|
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
|
using var readScope = context.App.Services.CreateScope();
|
|
var channels = readScope.ServiceProvider.GetRequiredService<IEmailChannelRepository>();
|
|
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<SmtpChannelSettings>(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<JsonElement>();
|
|
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<IEmailChannelRepository>().GetByIdAsync(channel.Id))!;
|
|
Assert.Equal(context.ServiceId, saved.ServiceId);
|
|
Assert.Equal(2, saved.Priority);
|
|
Assert.Equal(25, saved.DailyLimit);
|
|
}
|
|
|
|
private static async Task<EmailChannel> 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<IEmailChannelRepository>().AddAsync(channel);
|
|
await scope.ServiceProvider.GetRequiredService<IEmailChannelUsageRepository>()
|
|
.IncrementUsageAsync(channel.Id, DateOnly.FromDateTime(DateTime.UtcNow));
|
|
return channel;
|
|
}
|
|
}
|