test(e2e): cover LDAP mapping create/edit/delete round-trip
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using Microsoft.Playwright;
|
||||
using ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.Cluster;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.Admin;
|
||||
|
||||
/// <summary>
|
||||
/// End-to-end CRUD round-trip for the LDAP Group Mappings admin page.
|
||||
/// Covers create → edit → delete via the UI against the running dev cluster.
|
||||
/// </summary>
|
||||
[Collection("Playwright")]
|
||||
public class LdapMappingCrudTests
|
||||
{
|
||||
private readonly PlaywrightFixture _fixture;
|
||||
|
||||
public LdapMappingCrudTests(PlaywrightFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task CreateEditDelete_LdapMapping_RoundTrips()
|
||||
{
|
||||
Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason);
|
||||
|
||||
// Keep the group name short and unique to avoid collisions with other test runs.
|
||||
var group = $"zztest-grp-{Guid.NewGuid():N}"[..18];
|
||||
|
||||
var page = await _fixture.NewAuthenticatedPageAsync();
|
||||
|
||||
// ── CREATE ────────────────────────────────────────────────────────────────
|
||||
await page.GotoAsync($"{PlaywrightFixture.BaseUrl}/admin/ldap-mappings/create");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// The LDAP Group Name label has no `for=` attribute so GetByLabel does not
|
||||
// work. Locate the input that immediately follows the label text instead.
|
||||
await page.Locator("label:has-text('LDAP Group Name') + input.form-control.form-control-sm").FillAsync(group);
|
||||
await page.SelectOptionAsync(".form-select.form-select-sm", "Designer");
|
||||
await page.ClickAsync("button.btn.btn-success.btn-sm:has-text('Save')");
|
||||
|
||||
// Wait for Blazor enhanced navigation back to the list page.
|
||||
await PlaywrightFixture.WaitForPathAsync(page, "/admin/ldap-mappings", excludePath: "/create");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// The new row must be visible on the list.
|
||||
var newRow = page.Locator("tr", new() { HasText = group });
|
||||
await Assertions.Expect(newRow).ToBeVisibleAsync();
|
||||
|
||||
// ── EDIT ──────────────────────────────────────────────────────────────────
|
||||
// Click the Edit button within that row.
|
||||
await newRow.Locator("button.btn.btn-outline-primary.btn-sm:has-text('Edit')").ClickAsync();
|
||||
|
||||
await PlaywrightFixture.WaitForPathAsync(page, "/edit");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Change the role to Viewer and save.
|
||||
await page.SelectOptionAsync(".form-select.form-select-sm", "Viewer");
|
||||
await page.ClickAsync("button.btn.btn-success.btn-sm:has-text('Save')");
|
||||
|
||||
await PlaywrightFixture.WaitForPathAsync(page, "/admin/ldap-mappings", excludePath: "/edit");
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// Row must still be present after the edit.
|
||||
var editedRow = page.Locator("tr", new() { HasText = group });
|
||||
await Assertions.Expect(editedRow).ToBeVisibleAsync();
|
||||
|
||||
// ── DELETE (no confirmation dialog) ───────────────────────────────────────
|
||||
// Scope all dropdown interactions to the row's .dropdown container so we
|
||||
// never accidentally match a Delete button from another row's menu.
|
||||
var rowDropdown = editedRow.Locator(".dropdown");
|
||||
var kebab = rowDropdown.Locator("button[aria-label^='More actions']");
|
||||
await kebab.ClickAsync();
|
||||
|
||||
// Click Delete in the now-open dropdown within this row — no confirm dialog.
|
||||
var deleteBtn = rowDropdown.Locator(".dropdown-menu button.dropdown-item.text-danger");
|
||||
await deleteBtn.ClickAsync();
|
||||
|
||||
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
|
||||
|
||||
// The row must be gone.
|
||||
await Assertions.Expect(page.Locator("tr", new() { HasText = group }))
|
||||
.ToHaveCountAsync(0, new() { Timeout = 10_000 });
|
||||
|
||||
// TODO: best-effort cleanup if a mid-test failure left a zztest-grp-* row.
|
||||
// The happy path deletes via the UI above; no CLI cleanup needed for the passing case.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user