Files
hrynco-notification-service/HrynCo.NotificationService.Web.IntegrationTests/WorkerTemplateIntegrationTests.cs
agrynco 81654c0d33 feat(templates): add service language template management
Add normalized service and template catalogs, scoped administration, migration, validation, and regression coverage.

Ref: IT-1601
2026-10-17 22:02:43 +03:00

94 lines
5.7 KiB
C#

using HrynCo.NotificationService.Contracts.Messages;
using HrynCo.NotificationService.DAL.Abstract.Repositories;
using HrynCo.NotificationService.DAL.Abstract.Templates;
using HrynCo.NotificationService.DAL.EF;
using HrynCo.NotificationService.Worker.Services;
using HrynCo.NotificationService.Worker.Services.EmailProcessing;
using Microsoft.Extensions.DependencyInjection;
namespace HrynCo.NotificationService.Web.IntegrationTests;
public sealed class WorkerTemplateIntegrationTests(TemplateDatabaseFixture fixture) : IClassFixture<TemplateDatabaseFixture>
{
[Fact]
public async Task Worker_UsesExactLanguageContentAndCurrentSharedContract()
{
var connection = await fixture.CreateDatabaseAsync();
using var provider = new ServiceCollection().AddNotificationDataAccess(connection).AddNotificationWorkerServices().BuildServiceProvider();
var codes = new[] { "de", "en", "ru", "uk", "ru-RU" };
foreach (var code in codes)
await AddVersionAsync(provider, code);
foreach (var code in codes)
{
using var readScope = provider.CreateScope();
var template = await readScope.ServiceProvider.GetRequiredService<IEmailTemplateService>().GetAsync("TestService", "Delivery", code, default);
var rendered = readScope.ServiceProvider.GetRequiredService<IEmailTemplateRenderingService>().Render(template, Message(code));
Assert.Equal(code + " A < B", rendered.Subject);
Assert.Equal("<p>A &lt; B</p>", rendered.HtmlBody);
Assert.Equal("A < B", rendered.TextBody);
}
using (var updateScope = provider.CreateScope())
{
var definitions = updateScope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionRepository>();
var definition = (await definitions.GetDefinitionAsync("TestService", "Delivery"))!;
definition.Variables = [new EmailTemplateVariable { Name = "Extra", Required = true }];
await definitions.SaveDefinitionAsync(definition, false);
}
using var finalScope = provider.CreateScope();
var loader = finalScope.ServiceProvider.GetRequiredService<IEmailTemplateService>();
var updated = await loader.GetAsync("TestService", "Delivery", "ru-RU", default);
var error = Assert.Throws<InvalidDataException>(() => finalScope.ServiceProvider.GetRequiredService<IEmailTemplateRenderingService>().Render(updated, Message("ru-RU")));
Assert.Contains("Extra", error.Message);
await Assert.ThrowsAsync<InvalidOperationException>(() => loader.GetAsync("TestService", "Delivery", "RU-ru", default));
await Assert.ThrowsAsync<InvalidOperationException>(() => loader.GetAsync("TestService", "Missing", "en", default));
}
[Fact]
public async Task Worker_CompatibilityRetryPreservesExactVersionPriorityAndRepositoryCodes()
{
var connection = await fixture.CreateDatabaseAsync();
using var provider = new ServiceCollection().AddNotificationDataAccess(connection).AddNotificationWorkerServices().BuildServiceProvider();
await AddVersionAsync(provider, "ru");
await AddVersionAsync(provider, "ru-RU");
using (var legacyScope = provider.CreateScope())
{
var loader = legacyScope.ServiceProvider.GetRequiredService<IEmailTemplateService>();
Assert.Equal("ru", (await loader.GetAsync("TestService", "Delivery", "RU", default)).LanguageCode);
Assert.Equal("ru", (await loader.GetAsync("TestService", "Delivery", " ru ", default)).LanguageCode);
Assert.Null(await legacyScope.ServiceProvider.GetRequiredService<IEmailTemplateRepository>().GetAsync("TestService", "Delivery", "RU"));
}
using (var catalogScope = provider.CreateScope())
{
var services = catalogScope.ServiceProvider.GetRequiredService<INotificationServiceRepository>();
var service = (await services.GetAllAsync()).Single(s => s.Name == "TestService");
service.Languages = [..service.Languages, new ServiceLanguageInfo { Code = "RU" }];
await services.SaveAsync(service, false);
}
await AddVersionAsync(provider, "RU");
using var exactScope = provider.CreateScope();
var exactLoader = exactScope.ServiceProvider.GetRequiredService<IEmailTemplateService>();
Assert.Equal("RU", (await exactLoader.GetAsync("TestService", "Delivery", "RU", default)).LanguageCode);
Assert.Equal("ru-RU", (await exactLoader.GetAsync("TestService", "Delivery", "ru-RU", default)).LanguageCode);
Assert.Equal("ru", (await exactLoader.GetAsync("TestService", "Delivery", "ru", default)).LanguageCode);
await Assert.ThrowsAsync<InvalidOperationException>(() => exactLoader.GetAsync("TestService", "Delivery", "RU-ru", default));
await Assert.ThrowsAsync<InvalidOperationException>(() => exactLoader.GetAsync("TestService", "Delivery", "zz", default));
}
private static async Task AddVersionAsync(ServiceProvider provider, string code)
{
using var scope = provider.CreateScope();
await scope.ServiceProvider.GetRequiredService<IEmailTemplateRepository>().AddAsync(new EmailTemplate
{
ServiceName = "TestService", Key = "Delivery", LanguageCode = code,
Subject = code + " {{Name}}", HtmlBody = "<p>{{Name}}</p>", TextBody = "{{Name}}",
Variables = [new EmailTemplateVariable { Name = "Name", Required = true }]
});
}
private static SendEmailMessageData Message(string code) => new()
{
ServiceName = "TestService", TemplateKey = "Delivery", LanguageCode = code,
RecipientEmail = "test@example.invalid", RecipientName = "Test", Variables = new Dictionary<string, string> { ["Name"] = "A < B" }
};
}