test(playwright): Templates duplicate-name + create-cancel edge cases (Wave 4)
This commit is contained in:
@@ -120,4 +120,96 @@ public class TemplateCrudTests
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task CreateTemplate_DuplicateName_ShowsInlineError()
|
||||
{
|
||||
Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason);
|
||||
|
||||
// CLI-seed an existing base template, then UI-attempt to create a duplicate.
|
||||
// Base (non-derived) Template.Name has a unique index
|
||||
// (HasIndex(t => t.Name).IsUnique().HasFilter("[IsDerived]=0")) and
|
||||
// TemplateService.CreateTemplateAsync has no friendly duplicate pre-check,
|
||||
// so the DB-constraint exception is caught into _formError and rendered inline
|
||||
// in div.text-danger.small with no navigation (stays on /create).
|
||||
// (Empirically confirmed: duplicate create surfaces inline; duplicate-name path used.)
|
||||
var name = CliRunner.UniqueName("tmpl");
|
||||
var seededId = await CliRunner.CreateTemplateAsync(name);
|
||||
|
||||
try
|
||||
{
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/design/templates/create");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Fill the Name input with the duplicate name and click Create.
|
||||
await page.Locator("div.mb-3:has(label:has-text('Name')) input.form-control").FillAsync(name);
|
||||
await page.ClickAsync("button.btn.btn-success:has-text('Create')");
|
||||
|
||||
// Web-first assertions: the inline error becomes visible and we stay on /create.
|
||||
// Do NOT assert a literal message — it is the DB-constraint exception text.
|
||||
await Assertions.Expect(page.Locator("div.text-danger.small")).ToBeVisibleAsync();
|
||||
await Assertions.Expect(page)
|
||||
.ToHaveURLAsync(new System.Text.RegularExpressions.Regex("/design/templates/create"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Delete the seeded source template, then sweep any leftover by name.
|
||||
await CliRunner.DeleteTemplateAsync(seededId);
|
||||
try
|
||||
{
|
||||
foreach (var id in await CliRunner.ListTemplateIdsByNamePrefixAsync(name))
|
||||
{
|
||||
await CliRunner.DeleteTemplateAsync(id);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Best-effort — swallow to avoid masking the original test failure.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task CreateTemplate_Cancel_ReturnsToListWithoutCreating()
|
||||
{
|
||||
Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason);
|
||||
|
||||
var name = CliRunner.UniqueName("tmpl");
|
||||
|
||||
try
|
||||
{
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/design/templates/create");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Fill the Name input, then click Cancel — Blazor navigates back to the list.
|
||||
await page.Locator("div.mb-3:has(label:has-text('Name')) input.form-control").FillAsync(name);
|
||||
await page.ClickAsync("button.btn.btn-outline-secondary:has-text('Cancel')");
|
||||
|
||||
// excludePath: "/create" rejects the /design/templates/create URL we came from.
|
||||
await PlaywrightFixture.WaitForPathAsync(page, "/design/templates", excludePath: "/create");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Nothing was created: no template exists with our unique name.
|
||||
Assert.Empty(await CliRunner.ListTemplateIdsByNamePrefixAsync(name));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Defensive sweep by name in case of an unexpected create.
|
||||
try
|
||||
{
|
||||
foreach (var id in await CliRunner.ListTemplateIdsByNamePrefixAsync(name))
|
||||
{
|
||||
await CliRunner.DeleteTemplateAsync(id);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Best-effort — swallow to avoid masking the original test failure.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user