8e81572386
Add revision-safe service and template APIs, channel mapping, and validated admin controls. Ref: IT-1601
93 lines
6.0 KiB
C#
93 lines
6.0 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Nodes;
|
|
using HrynCo.NotificationService.DAL.Abstract.Providers;
|
|
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
|
using HrynCo.NotificationService.DAL.EF;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace HrynCo.NotificationService.Web.IntegrationTests;
|
|
|
|
public sealed class EmailChannelApiTests(TemplateDatabaseFixture fixture) : IClassFixture<TemplateDatabaseFixture>
|
|
{
|
|
[Fact]
|
|
public async Task SmtpSettingsRoundTripThroughCreateReadUpdateListAndDelete()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var request = Content("smtp.example.invalid", 2525, "test-only-user");
|
|
var created = await context.Client.PostAsJsonAsync("/api/v1/email-channels", request);
|
|
Assert.Equal(HttpStatusCode.Created, created.StatusCode);
|
|
var id = (await created.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("data").GetGuid();
|
|
var original = (await context.Client.GetFromJsonAsync<JsonElement>($"/api/v1/email-channels/{id}")).GetProperty("data");
|
|
Assert.Equal("smtp.example.invalid", original.GetProperty("settings").GetProperty("host").GetString());
|
|
Assert.Equal(2525, original.GetProperty("settings").GetProperty("port").GetInt32());
|
|
Assert.Equal("test-only-user", original.GetProperty("settings").GetProperty("username").GetString());
|
|
Assert.Equal(HttpStatusCode.OK, (await context.Client.PutAsJsonAsync($"/api/v1/email-channels/{id}", Content("updated.example.invalid", 2526, "updated-user"))).StatusCode);
|
|
var all = (await context.Client.GetFromJsonAsync<JsonElement>("/api/v1/email-channels/all")).GetProperty("data");
|
|
var updated = Assert.Single(all.EnumerateArray());
|
|
Assert.Equal("updated.example.invalid", updated.GetProperty("settings").GetProperty("host").GetString());
|
|
Assert.Equal("updated-user", updated.GetProperty("settings").GetProperty("username").GetString());
|
|
Assert.Equal(2526, updated.GetProperty("settings").GetProperty("port").GetInt32());
|
|
Assert.Equal("test-only-value", updated.GetProperty("settings").GetProperty("password").GetString());
|
|
Assert.False(updated.GetProperty("settings").GetProperty("useSsl").GetBoolean());
|
|
Assert.Equal("sender@example.invalid", updated.GetProperty("settings").GetProperty("fromEmail").GetString());
|
|
Assert.Equal("Test sender", updated.GetProperty("settings").GetProperty("fromName").GetString());
|
|
var filtered = await context.Client.GetFromJsonAsync<JsonElement>("/api/v1/email-channels?serviceName=IndependentChannelService");
|
|
Assert.Single(filtered.GetProperty("data").EnumerateArray());
|
|
Assert.Equal(HttpStatusCode.OK, (await context.Client.DeleteAsync($"/api/v1/email-channels/{id}")).StatusCode);
|
|
Assert.Equal(HttpStatusCode.NotFound, (await context.Client.GetAsync($"/api/v1/email-channels/{id}")).StatusCode);
|
|
Assert.Empty((await context.Client.GetFromJsonAsync<JsonElement>("/api/v1/email-channels/all")).GetProperty("data").EnumerateArray());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAllIncludesChannelsWhoseServiceNameHasNoServiceRecord()
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
using var scope = context.App.Services.CreateScope();
|
|
var channels = scope.ServiceProvider.GetRequiredService<IEmailChannelRepository>();
|
|
foreach (var serviceName in new[] { "TestService", "OrphanChannelService" })
|
|
await channels.AddAsync(new EmailChannel
|
|
{
|
|
ServiceName = serviceName, EmailChannelType = EmailChannelType.Smtp,
|
|
Settings = new SmtpChannelSettings { Host = "localhost", FromEmail = "test@example.invalid" }
|
|
});
|
|
await scope.ServiceProvider.GetRequiredService<NotificationDbContext>().SaveChangesAsync();
|
|
var all = (await context.Client.GetFromJsonAsync<JsonElement>("/api/v1/email-channels/all")).GetProperty("data");
|
|
Assert.Equal(2, all.GetArrayLength());
|
|
Assert.Contains(all.EnumerateArray(), c => c.GetProperty("serviceName").GetString() == "OrphanChannelService");
|
|
Assert.All(all.EnumerateArray(), c => Assert.NotEqual(Guid.Empty, c.GetProperty("id").GetGuid()));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("nullSettings")]
|
|
[InlineData("invalidPort")]
|
|
[InlineData("blankHost")]
|
|
[InlineData("unsupportedType")]
|
|
[InlineData("blankService")]
|
|
public async Task InvalidSmtpCreateReturnsValidationEnvelopeWithoutPersisting(string scenario)
|
|
{
|
|
await using var context = await DefinitionApiTestContext.CreateAsync(fixture);
|
|
var body = JsonSerializer.SerializeToNode(Content("smtp.example.invalid", 2525, "test-user"), new JsonSerializerOptions(JsonSerializerDefaults.Web))!.AsObject();
|
|
switch (scenario)
|
|
{
|
|
case "nullSettings": body["settings"] = null; break;
|
|
case "invalidPort": body["settings"]!["port"] = 0; break;
|
|
case "blankHost": body["settings"]!["host"] = " "; break;
|
|
case "unsupportedType": body["channelType"] = 99; break;
|
|
case "blankService": body["serviceName"] = " "; break;
|
|
}
|
|
var response = await context.Client.PostAsJsonAsync("/api/v1/email-channels", body);
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
Assert.Equal("InvalidRequest", (await response.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("error").GetProperty("code").GetString());
|
|
Assert.Empty((await context.Client.GetFromJsonAsync<JsonElement>("/api/v1/email-channels/all")).GetProperty("data").EnumerateArray());
|
|
}
|
|
|
|
private static object Content(string host, int port, string username) => new
|
|
{
|
|
serviceName = "IndependentChannelService", priority = 1, channelType = 1,
|
|
settings = new { host, port, username, password = "test-only-value", useSsl = false, fromEmail = "sender@example.invalid", fromName = "Test sender" },
|
|
dailyLimit = 100, monthlyLimit = 1000, warnThresholdPercent = 90, isActive = true
|
|
};
|
|
}
|