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
This commit is contained in:
+19
-4
@@ -12,7 +12,7 @@ public sealed class SendEmailDeliveryValidatorTests
|
||||
string? error = SendEmailDeliveryValidator.GetValidationError(
|
||||
CreateMessage(),
|
||||
CreateContext(),
|
||||
SendEmailConsumer.SupportedMessageType);
|
||||
SupportedMessageType.SendEmailV1);
|
||||
|
||||
Assert.Null(error);
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public sealed class SendEmailDeliveryValidatorTests
|
||||
string? error = SendEmailDeliveryValidator.GetValidationError(
|
||||
CreateMessage(),
|
||||
context,
|
||||
SendEmailConsumer.SupportedMessageType);
|
||||
SupportedMessageType.SendEmailV1);
|
||||
|
||||
Assert.Equal("AMQP MessageId is required.", error);
|
||||
}
|
||||
@@ -41,18 +41,33 @@ public sealed class SendEmailDeliveryValidatorTests
|
||||
string? error = SendEmailDeliveryValidator.GetValidationError(
|
||||
CreateMessage(),
|
||||
context,
|
||||
SendEmailConsumer.SupportedMessageType);
|
||||
SupportedMessageType.SendEmailV1);
|
||||
|
||||
Assert.Equal("Unsupported AMQP message type 'Notification.SendEmail.v2'.", error);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Notification.SendPush.v1")]
|
||||
[InlineData("notification.sendemail.v1")]
|
||||
[InlineData("SendEmailV1")]
|
||||
[InlineData("0")]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
public void OtherOrMissingWireType_IsRejected(string? wireType)
|
||||
{
|
||||
string? error = SendEmailDeliveryValidator.GetValidationError(CreateMessage(),
|
||||
CreateContext() with { MessageType = wireType }, SupportedMessageType.SendEmailV1);
|
||||
|
||||
Assert.Equal($"Unsupported AMQP message type '{wireType ?? "<missing>"}'.", error);
|
||||
}
|
||||
|
||||
private static RabbitMqMessageContext CreateContext() => new()
|
||||
{
|
||||
QueueName = SendEmailConsumer.IncomingQueue,
|
||||
Exchange = string.Empty,
|
||||
RoutingKey = SendEmailConsumer.IncomingQueue,
|
||||
MessageId = Guid.NewGuid().ToString("D"),
|
||||
MessageType = SendEmailConsumer.SupportedMessageType,
|
||||
MessageType = "Notification.SendEmail.v1",
|
||||
CorrelationId = "correlation-id",
|
||||
ContentType = "application/json"
|
||||
};
|
||||
|
||||
@@ -23,12 +23,12 @@ public sealed class SendEmailServiceTests
|
||||
Password = "not-a-real-secret",
|
||||
UseSsl = true,
|
||||
FromEmail = "notifications@example.com",
|
||||
FromName = "StoreMate"
|
||||
FromName = "Invemory"
|
||||
};
|
||||
var channel = new EmailChannel
|
||||
{
|
||||
Id = channelId,
|
||||
ServiceName = "StoreMate-Prod",
|
||||
ServiceId = Guid.NewGuid(),
|
||||
Priority = 1,
|
||||
EmailChannelType = EmailChannelType.Smtp,
|
||||
Settings = settings,
|
||||
@@ -36,7 +36,7 @@ public sealed class SendEmailServiceTests
|
||||
};
|
||||
var template = new EmailTemplate
|
||||
{
|
||||
ServiceName = "StoreMate-Prod",
|
||||
ServiceName = "Invemory-Prod",
|
||||
Key = "EmailVerification",
|
||||
LanguageCode = "uk",
|
||||
Subject = "Verify {{AppName}}",
|
||||
@@ -46,17 +46,21 @@ public sealed class SendEmailServiceTests
|
||||
};
|
||||
|
||||
IEmailChannelRepository channels = Substitute.For<IEmailChannelRepository>();
|
||||
channels.GetByServiceAsync("StoreMate-Prod", Arg.Any<CancellationToken>())
|
||||
channels.GetByServiceAsync(channel.ServiceId, Arg.Any<CancellationToken>())
|
||||
.Returns([channel]);
|
||||
var services = Substitute.For<INotificationServiceRepository>();
|
||||
services.GetByNameAsync("Invemory-Prod", Arg.Any<CancellationToken>())
|
||||
.Returns(new NotificationServiceInfo { Id = channel.ServiceId, Name = "Invemory-Prod" });
|
||||
IEmailChannelUsageRepository usage = Substitute.For<IEmailChannelUsageRepository>();
|
||||
IEmailTemplateService templates = Substitute.For<IEmailTemplateService>();
|
||||
templates.GetAsync("StoreMate-Prod", "EmailVerification", "uk", Arg.Any<CancellationToken>())
|
||||
templates.GetAsync("Invemory-Prod", "EmailVerification", "uk", Arg.Any<CancellationToken>())
|
||||
.Returns(template);
|
||||
var renderer = new EmailTemplateRenderingService();
|
||||
var smtp = new RecordingSmtpEmailSender();
|
||||
INotificationResultPublisher resultPublisher = Substitute.For<INotificationResultPublisher>();
|
||||
var service = new SendEmailService(
|
||||
channels,
|
||||
services,
|
||||
usage,
|
||||
templates,
|
||||
renderer,
|
||||
@@ -71,12 +75,12 @@ public sealed class SendEmailServiceTests
|
||||
},
|
||||
Data = new SendEmailMessageData
|
||||
{
|
||||
ServiceName = "StoreMate-Prod",
|
||||
ServiceName = "Invemory-Prod",
|
||||
TemplateKey = "EmailVerification",
|
||||
RecipientEmail = "owner@example.com",
|
||||
RecipientName = "Owner",
|
||||
LanguageCode = "uk",
|
||||
Variables = new Dictionary<string, string> { ["AppName"] = "StoreMate" }
|
||||
Variables = new Dictionary<string, string> { ["AppName"] = "Invemory" }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -84,7 +88,7 @@ public sealed class SendEmailServiceTests
|
||||
|
||||
Assert.Equal(1, smtp.SendCount);
|
||||
Assert.Same(settings, smtp.Settings);
|
||||
Assert.Equal("Verify StoreMate", smtp.Email?.Subject);
|
||||
Assert.Equal("Verify Invemory", smtp.Email?.Subject);
|
||||
Assert.Equal("owner@example.com", smtp.RecipientEmail);
|
||||
Assert.Equal("Owner", smtp.RecipientName);
|
||||
await usage.Received(1).IncrementUsageAsync(
|
||||
|
||||
Reference in New Issue
Block a user