50033a5bd4
Encode template variables in HTML bodies while preserving text and subjects. Ref: IT-1115
89 lines
3.2 KiB
C#
89 lines
3.2 KiB
C#
namespace HrynCo.NotificationService.Services.Tests.EmailProcessing;
|
|
|
|
using HrynCo.NotificationService.Contracts.Messages;
|
|
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
|
using HrynCo.NotificationService.Worker.Services.EmailProcessing;
|
|
|
|
public sealed class EmailTemplateRenderingServiceTests
|
|
{
|
|
private readonly EmailTemplateRenderingService _service = new();
|
|
|
|
[Fact]
|
|
public void Render_InterpolatesItemTrackerVariables()
|
|
{
|
|
EmailTemplate template = CreateTemplate();
|
|
SendEmailMessageData data = CreateData(new Dictionary<string, string>
|
|
{
|
|
["AppName"] = "StoreMate",
|
|
["VerificationUrl"] = "https://example.invalid/verify"
|
|
});
|
|
|
|
RenderedEmail result = _service.Render(template, data);
|
|
|
|
Assert.Equal("Verify StoreMate", result.Subject);
|
|
Assert.Equal("<a href=\"https://example.invalid/verify\">Verify</a>", result.HtmlBody);
|
|
Assert.Equal("Verify at https://example.invalid/verify", result.TextBody);
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_WhenRequiredVariableIsMissing_ThrowsObservableFailure()
|
|
{
|
|
EmailTemplate template = CreateTemplate();
|
|
SendEmailMessageData data = CreateData(new Dictionary<string, string>
|
|
{
|
|
["AppName"] = "StoreMate"
|
|
});
|
|
|
|
InvalidDataException exception = Assert.Throws<InvalidDataException>(
|
|
() => _service.Render(template, data));
|
|
|
|
Assert.Equal("Required template variables are missing: VerificationUrl.", exception.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_HtmlEncodesVariablesWithoutChangingSubjectOrTextBody()
|
|
{
|
|
EmailTemplate template = CreateTemplate();
|
|
SendEmailMessageData data = CreateData(new Dictionary<string, string>
|
|
{
|
|
["AppName"] = "Invemory <script>alert('xss')</script>",
|
|
["VerificationUrl"] = "https://example.invalid/verify?next=\" onclick=\"alert('xss')"
|
|
});
|
|
|
|
RenderedEmail result = _service.Render(template, data);
|
|
|
|
Assert.Equal("Verify Invemory <script>alert('xss')</script>", result.Subject);
|
|
Assert.Equal(
|
|
"<a href=\"https://example.invalid/verify?next=" onclick="alert('xss')\">Verify</a>",
|
|
result.HtmlBody);
|
|
Assert.Equal(
|
|
"Verify at https://example.invalid/verify?next=\" onclick=\"alert('xss')",
|
|
result.TextBody);
|
|
}
|
|
|
|
private static EmailTemplate CreateTemplate() => new()
|
|
{
|
|
ServiceName = "StoreMate-Prod",
|
|
Key = "EmailVerification",
|
|
LanguageCode = "uk",
|
|
Subject = "Verify {{AppName}}",
|
|
HtmlBody = "<a href=\"{{VerificationUrl}}\">Verify</a>",
|
|
TextBody = "Verify at {{VerificationUrl}}",
|
|
Variables =
|
|
[
|
|
new EmailTemplateVariable { Name = "AppName", Required = true },
|
|
new EmailTemplateVariable { Name = "VerificationUrl", Required = true }
|
|
]
|
|
};
|
|
|
|
private static SendEmailMessageData CreateData(IReadOnlyDictionary<string, string> variables) => new()
|
|
{
|
|
ServiceName = "StoreMate-Prod",
|
|
TemplateKey = "EmailVerification",
|
|
RecipientEmail = "owner@example.com",
|
|
RecipientName = "Owner",
|
|
LanguageCode = "uk",
|
|
Variables = variables
|
|
};
|
|
}
|