Files
agrynco 1631786ce2 feat(push): add service-owned firebase channels and delivery
Add push contracts, provider delivery and channel diagnostics. Link email channels to services and document migration and validation.

Ref: IT-1074
2026-10-24 12:31:35 +03:00

113 lines
4.1 KiB
C#

using System.Reflection;
using System.Text.Json;
using HrynCo.NotificationService.DAL.Abstract.Providers;
using HrynCo.NotificationService.Web.Controllers.Admin;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace HrynCo.NotificationService.Web.IntegrationTests;
public sealed class AdminSmtpTestControllerTests
{
private static readonly Guid ChannelId = Guid.NewGuid();
[Fact]
public async Task BlankPasswordUsesSavedSecretAndCurrentUnsavedSender()
{
var (controller, recorder) = CreateController();
var response = await controller.TestSmtp(Request(), CancellationToken.None);
Assert.True(Succeeded(response));
Assert.Equal("saved-test-secret", recorder.SentCommand?.Password);
Assert.Equal("changed@example.invalid", recorder.SentCommand?.FromEmail);
Assert.Equal("Changed sender", recorder.SentCommand?.FromName);
Assert.Equal(1, recorder.LookupCount);
Assert.DoesNotContain("saved-test-secret", JsonSerializer.Serialize(((OkObjectResult)response).Value));
}
[Fact]
public async Task ExplicitPasswordOverridesSavedWithoutLookup()
{
var (controller, recorder) = CreateController();
var response = await controller.TestSmtp(Request() with { Password = "typed-test-secret" }, CancellationToken.None);
Assert.True(Succeeded(response));
Assert.Equal("typed-test-secret", recorder.SentCommand?.Password);
Assert.Equal(0, recorder.LookupCount);
}
[Theory]
[InlineData("host")]
[InlineData("port")]
[InlineData("username")]
[InlineData("ssl")]
public async Task ChangedConnectionRequiresExplicitPassword(string field)
{
var (controller, recorder) = CreateController();
var request = field switch
{
"host" => Request() with { Host = "other.example.invalid" },
"port" => Request() with { Port = 2525 },
"username" => Request() with { Username = "other-user" },
_ => Request() with { UseSsl = false }
};
var response = await controller.TestSmtp(request, CancellationToken.None);
Assert.False(Succeeded(response));
Assert.Null(recorder.SentCommand);
}
[Fact]
public async Task UnknownChannelDoesNotSend()
{
var (controller, recorder) = CreateController();
recorder.Channel = null;
var response = await controller.TestSmtp(Request(), CancellationToken.None);
Assert.False(Succeeded(response));
Assert.Null(recorder.SentCommand);
}
[Fact]
public async Task NewChannelKeepsAdHocTestBehavior()
{
var (controller, recorder) = CreateController();
var response = await controller.TestSmtp(Request() with { ChannelId = null }, CancellationToken.None);
Assert.True(Succeeded(response));
Assert.Equal(string.Empty, recorder.SentCommand?.Password);
Assert.Equal(0, recorder.LookupCount);
}
private static (AdminChannelsController Controller, RecordingAdminSmtpMediator Recorder) CreateController()
{
var mediator = DispatchProxy.Create<IMediator, RecordingAdminSmtpMediator>();
var recorder = (RecordingAdminSmtpMediator)mediator;
recorder.Channel = new EmailChannel
{
Id = ChannelId,
ServiceId = Guid.NewGuid(),
EmailChannelType = EmailChannelType.Smtp,
Settings = new SmtpChannelSettings
{
Host = "smtp.example.invalid", Port = 587,
Username = "test-user", Password = "saved-test-secret", UseSsl = true
}
};
return (new AdminChannelsController(mediator, null!), recorder);
}
private static TestSmtpRequest Request() => new(
"smtp.example.invalid", 587, "test-user", "", true,
"changed@example.invalid", "Changed sender", "recipient@example.invalid", ChannelId);
private static bool Succeeded(IActionResult response)
{
var body = JsonSerializer.Serialize(((OkObjectResult)response).Value);
return JsonDocument.Parse(body).RootElement.GetProperty("success").GetBoolean();
}
}