5a465d7257
Center action controls and adjust template editor field heights. Ref: IT-1601
135 lines
8.5 KiB
C#
135 lines
8.5 KiB
C#
using System.Net;
|
|
using System.Text.RegularExpressions;
|
|
using HrynCo.NotificationService.DAL.Abstract.Repositories;
|
|
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace HrynCo.NotificationService.Web.IntegrationTests;
|
|
|
|
public sealed class TemplateCatalogPresentationTests(TemplateDatabaseFixture fixture) : IClassFixture<TemplateDatabaseFixture>
|
|
{
|
|
[Fact]
|
|
public async Task EditorTabsShowSavedVersionsAfterInvalidUnsavedChanges()
|
|
{
|
|
var connection = await fixture.CreateDatabaseAsync();
|
|
await using var app = new TemplateWebApplicationFactory(connection);
|
|
using var scope = app.Services.CreateScope();
|
|
var service = (await scope.ServiceProvider.GetRequiredService<INotificationServiceRepository>().GetAllAsync()).Single();
|
|
var versions = scope.ServiceProvider.GetRequiredService<IEmailTemplateRepository>();
|
|
await versions.AddAsync(new EmailTemplate
|
|
{
|
|
ServiceName = service.Name, Key = "TabStatus", LanguageCode = "en",
|
|
Subject = "Saved", HtmlBody = "Saved", TextBody = "Saved"
|
|
});
|
|
var definition = (await scope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionRepository>()
|
|
.GetDefinitionAsync(service.Name, "TabStatus"))!;
|
|
using var client = app.CreateClient(new() { AllowAutoRedirect = false });
|
|
var baseUrl = $"/admin/services/{service.Id}/templates";
|
|
var html = await client.GetStringAsync($"{baseUrl}/{definition.Id}");
|
|
Assert.Matches("(?s)<span>en</span>\\s*<span class=\"template-language-status template-language-present\">Present</span>", html);
|
|
Assert.Matches("(?s)<span>uk</span>\\s*<span class=\"template-language-status template-language-missing\">Missing</span>", html);
|
|
|
|
var fields = TemplateEditorTestFields.Read(html);
|
|
TemplateEditorTestFields.SetLanguage(fields, "uk", "Unsaved", "", "");
|
|
fields["Languages[0].IsPresent"] = "false";
|
|
var response = await client.PostAsync(baseUrl + "/save", new FormUrlEncodedContent(fields));
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var invalidHtml = await response.Content.ReadAsStringAsync();
|
|
Assert.Matches("(?s)<span>en</span>\\s*<span class=\"template-language-status template-language-present\">Present</span>", invalidHtml);
|
|
Assert.Matches("(?s)<span>uk</span>\\s*<span class=\"template-language-status template-language-missing\">Missing</span>", invalidHtml);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CatalogStatusesUseExactCodes_AndEmptyDefinitionsShowEveryLanguageMissing()
|
|
{
|
|
var connection = await fixture.CreateDatabaseAsync();
|
|
await using var app = new TemplateWebApplicationFactory(connection);
|
|
using var scope = app.Services.CreateScope();
|
|
var services = scope.ServiceProvider.GetRequiredService<INotificationServiceRepository>();
|
|
var service = (await services.GetAllAsync()).Single();
|
|
service.Languages = new[] { "EN", "en", "ru", "ru-RU" }.Select(code => new ServiceLanguageInfo { Code = code }).ToList();
|
|
await services.SaveAsync(service, false);
|
|
var versions = scope.ServiceProvider.GetRequiredService<IEmailTemplateRepository>();
|
|
await versions.AddAsync(new EmailTemplate { ServiceName = service.Name, Key = "CaseCheck", LanguageCode = "en", Subject = "Hello", HtmlBody = "Hello", TextBody = "Hello" });
|
|
await versions.AddAsync(new EmailTemplate { ServiceName = service.Name, Key = "CaseCheck", LanguageCode = "ru", Subject = "Hello", HtmlBody = "Hello", TextBody = "Hello" });
|
|
var definitions = scope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionRepository>();
|
|
await definitions.SaveDefinitionAsync(new EmailTemplateDefinition { ServiceName = service.Name, Key = "Empty" }, true);
|
|
using var client = app.CreateClient();
|
|
var html = await client.GetStringAsync($"/admin/services/{service.Id}");
|
|
var catalog = Regex.Match(html, "<div class=\"service-template-catalog.*?</div>", RegexOptions.Singleline).Value;
|
|
Assert.Equal(4, Regex.Matches(catalog, "class=\"service-template-language-code\"").Count);
|
|
Assert.Contains(">EN</span>", catalog);
|
|
Assert.Contains(">en</span>", catalog);
|
|
Assert.Contains(">ru-RU</span>", catalog);
|
|
var row = TemplateRow(html, "CaseCheck");
|
|
Assert.Contains("data-language-code=\"en\" data-state=\"present\"", row);
|
|
Assert.Contains("data-language-code=\"EN\" data-state=\"missing\"", row);
|
|
Assert.Contains("data-language-code=\"ru\" data-state=\"present\"", row);
|
|
Assert.Contains("data-language-code=\"ru-RU\" data-state=\"missing\"", row);
|
|
Assert.Equal(2, Regex.Matches(row, ">Present</span>").Count);
|
|
Assert.Equal(2, Regex.Matches(row, ">Missing</span>").Count);
|
|
var empty = TemplateRow(html, "Empty");
|
|
Assert.Equal(4, Regex.Matches(empty, "data-state=\"missing\"").Count);
|
|
Assert.DoesNotContain("data-state=\"present\"", empty);
|
|
Assert.Equal(2, (await versions.GetAllAsync(service.Name)).Count);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task EmbeddedKeyFilterSurvivesMiss_AndClearAndEditorLinksStayWithinTheService()
|
|
{
|
|
var connection = await fixture.CreateDatabaseAsync();
|
|
await using var app = new TemplateWebApplicationFactory(connection);
|
|
using var scope = app.Services.CreateScope();
|
|
var service = (await scope.ServiceProvider.GetRequiredService<INotificationServiceRepository>().GetAllAsync()).Single();
|
|
var definitions = scope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionRepository>();
|
|
await definitions.SaveDefinitionAsync(new EmailTemplateDefinition { ServiceName = service.Name, Key = "Welcome" }, true);
|
|
await definitions.SaveDefinitionAsync(new EmailTemplateDefinition { ServiceName = service.Name, Key = "Other" }, true);
|
|
using var client = app.CreateClient();
|
|
var baseUrl = $"/admin/services/{service.Id}";
|
|
var miss = await client.GetStringAsync(baseUrl + "?key=Absent");
|
|
Assert.Matches("(?s)<th[^>]*>\\s*<form[^>]*method=\"get\"[^>]*class=\"template-key-filter\"", miss);
|
|
Assert.Contains("value=\"Absent\"", miss);
|
|
Assert.Contains("No templates match this key.", miss);
|
|
Assert.Contains("class=\"template-actions\">Action</th>", miss);
|
|
Assert.Contains($"href=\"{baseUrl}\" class=\"btn btn-outline-secondary btn-sm\">Clear</a>", miss);
|
|
var filtered = await client.GetStringAsync(baseUrl + "?key=Welcome");
|
|
Assert.Contains("<td>Welcome</td>", filtered);
|
|
Assert.DoesNotContain("<td>Other</td>", filtered);
|
|
Assert.Contains("keyFilter=Welcome", filtered);
|
|
Assert.Contains("aria-label=\"Edit template Welcome\"", filtered);
|
|
var cleared = await client.GetStringAsync(baseUrl);
|
|
Assert.Contains("<td>Welcome</td>", cleared);
|
|
Assert.Contains("<td>Other</td>", cleared);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task NoCatalogAndNoDefinitionsHaveExplicitStates_AndRetainTheTableHeader()
|
|
{
|
|
var connection = await fixture.CreateDatabaseAsync();
|
|
await using var app = new TemplateWebApplicationFactory(connection);
|
|
using var scope = app.Services.CreateScope();
|
|
var services = scope.ServiceProvider.GetRequiredService<INotificationServiceRepository>();
|
|
var service = new NotificationServiceInfo { Name = "NoLanguages" };
|
|
await services.SaveAsync(service, true);
|
|
using var client = app.CreateClient();
|
|
var baseUrl = $"/admin/services/{service.Id}";
|
|
var empty = await client.GetStringAsync(baseUrl);
|
|
Assert.Contains("No languages configured for this service.", empty);
|
|
Assert.Contains("template-key-filter", empty);
|
|
Assert.Contains("No email templates for this service yet.", empty);
|
|
await scope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionRepository>()
|
|
.SaveDefinitionAsync(new EmailTemplateDefinition { ServiceName = service.Name, Key = "Empty" }, true);
|
|
var withDefinition = await client.GetStringAsync(baseUrl);
|
|
Assert.Contains("No configured languages", TemplateRow(withDefinition, "Empty"));
|
|
Assert.DoesNotContain("data-state=", withDefinition);
|
|
Assert.DoesNotContain("No templates match this key.", withDefinition);
|
|
}
|
|
|
|
private static string TemplateRow(string html, string key)
|
|
{
|
|
var row = Regex.Match(html, "<tr>\\s*<td>" + Regex.Escape(WebUtility.HtmlEncode(key)) + "</td>.*?</tr>", RegexOptions.Singleline).Value;
|
|
Assert.NotEmpty(row);
|
|
return row;
|
|
}
|
|
}
|