81654c0d33
Add normalized service and template catalogs, scoped administration, migration, validation, and regression coverage. Ref: IT-1601
98 lines
4.3 KiB
C#
98 lines
4.3 KiB
C#
namespace HrynCo.NotificationService.Services.Tests.EmailProcessing;
|
|
|
|
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
|
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
|
using HrynCo.NotificationService.Worker.Services.EmailProcessing;
|
|
using NSubstitute;
|
|
|
|
public sealed class EmailTemplateServiceTests
|
|
{
|
|
[Theory]
|
|
[InlineData("RU")]
|
|
[InlineData(" ru ")]
|
|
[InlineData(" RU ")]
|
|
public async Task GetAsync_WhenExactVersionIsMissing_RetriesLegacyTrimmedLowercaseCode(string requestedCode)
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
var expected = Template("ru");
|
|
repository.GetAsync("TestService", "Welcome", "ru", Arg.Any<CancellationToken>()).Returns(expected);
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
Assert.Same(expected, await service.GetAsync("TestService", "Welcome", requestedCode, default));
|
|
Assert.Equal(new[] { requestedCode, "ru" }, RequestedCodes(repository));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_WhenBothExactAndLowercaseVersionsExist_PrefersExactVersion()
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
var expected = Template("RU");
|
|
repository.GetAsync("TestService", "Welcome", "RU", Arg.Any<CancellationToken>()).Returns(expected);
|
|
repository.GetAsync("TestService", "Welcome", "ru", Arg.Any<CancellationToken>()).Returns(Template("ru"));
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
Assert.Same(expected, await service.GetAsync("TestService", "Welcome", "RU", default));
|
|
Assert.Equal(new[] { "RU" }, RequestedCodes(repository));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_WhenExactRegionalVersionExists_DoesNotNormalizeIt()
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
var expected = Template("ru-RU");
|
|
repository.GetAsync("TestService", "Welcome", "ru-RU", Arg.Any<CancellationToken>()).Returns(expected);
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
Assert.Same(expected, await service.GetAsync("TestService", "Welcome", "ru-RU", default));
|
|
Assert.Equal(new[] { "ru-RU" }, RequestedCodes(repository));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_WhenMissingCodeIsAlreadyCanonical_QueriesOnlyOnce()
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
var error = await Assert.ThrowsAsync<InvalidOperationException>(() => service.GetAsync("TestService", "Welcome", "zz", default));
|
|
|
|
Assert.Contains("language='zz'", error.Message);
|
|
Assert.Equal(new[] { "zz" }, RequestedCodes(repository));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAsync_WhenRegionalLookupMisses_DoesNotScanOtherCaseOrRegionalVariants()
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
repository.GetAsync("TestService", "Welcome", "ru-RU", Arg.Any<CancellationToken>()).Returns(Template("ru-RU"));
|
|
repository.GetAsync("TestService", "Welcome", "ru", Arg.Any<CancellationToken>()).Returns(Template("ru"));
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
await Assert.ThrowsAsync<InvalidOperationException>(() => service.GetAsync("TestService", "Welcome", "RU-ru", default));
|
|
|
|
Assert.Equal(new[] { "RU-ru", "ru-ru" }, RequestedCodes(repository));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null)]
|
|
[InlineData("")]
|
|
[InlineData(" ")]
|
|
public async Task GetAsync_WhenCodeIsBlank_RejectsBeforeRepositoryLookup(string? code)
|
|
{
|
|
IEmailTemplateRepository repository = Substitute.For<IEmailTemplateRepository>();
|
|
var service = new EmailTemplateService(repository);
|
|
|
|
await Assert.ThrowsAsync<InvalidDataException>(() => service.GetAsync("TestService", "Welcome", code, default));
|
|
|
|
Assert.Empty(repository.ReceivedCalls());
|
|
}
|
|
|
|
private static EmailTemplate Template(string code) => new()
|
|
{
|
|
ServiceName = "TestService", Key = "Welcome", LanguageCode = code, Subject = "Subject " + code,
|
|
HtmlBody = "<p>Hello</p>", TextBody = "Hello"
|
|
};
|
|
|
|
private static string[] RequestedCodes(IEmailTemplateRepository repository) => repository.ReceivedCalls()
|
|
.Select(call => (string)call.GetArguments()[2]!).ToArray();
|
|
}
|