test(playwright): harden NotificationList toast + nav assertions (review fix)

This commit is contained in:
Joseph Doherty
2026-06-06 14:49:39 -04:00
parent 9c36036f2a
commit d03aa3c556
@@ -61,10 +61,16 @@ public class NotificationListCrudTests
var listRow = page.Locator("tr").Filter(new() { HasText = name });
await Assertions.Expect(listRow).ToBeVisibleAsync();
// Make the row locator strict-mode-safe: assert exactly one match before acting.
await Assertions.Expect(listRow).ToHaveCountAsync(1, new() { Timeout = 10_000 });
// ── ADD RECIPIENT ─────────────────────────────────────────────────────────
await listRow.Locator("button.btn-outline-primary.btn-sm:has-text('Edit')").ClickAsync();
// The Edit click triggers Blazor enhanced navigation (a SignalR round-trip that
// loads the edit form's data); wait for it to settle before asserting the heading.
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
await Assertions.Expect(page.Locator("h4:has-text('Edit Notification List')")).ToBeVisibleAsync();
// The edit page has TWO "Name" text inputs (list name + recipient name). Scope the
@@ -88,15 +94,18 @@ public class NotificationListCrudTests
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
var listRowAgain = page.Locator("tr").Filter(new() { HasText = name });
// Make the row locator strict-mode-safe: assert exactly one match before acting.
await Assertions.Expect(listRowAgain).ToHaveCountAsync(1, new() { Timeout = 10_000 });
await listRowAgain.Locator("button.btn-outline-danger.btn-sm:has-text('Delete')").ClickAsync();
// Confirm the global danger dialog.
await Assertions.Expect(page.Locator(".modal-footer .btn-danger")).ToBeVisibleAsync();
await page.Locator(".modal-footer .btn-danger").ClickAsync();
// Success toast appears (auto-dismisses at 5s, so assert promptly) and the row is gone.
await Assertions.Expect(page.Locator(".toast")).ToHaveCountAsync(1, new() { Timeout = 15_000 });
await Assertions.Expect(page.Locator(".toast-body:has-text('Deleted.')")).ToBeVisibleAsync();
// Assert the success toast in one web-first check — count + body text together — so the
// second assertion can't race the toast's 5s auto-dismiss.
await Assertions.Expect(page.Locator(".toast", new() { HasText = "Deleted." }))
.ToHaveCountAsync(1, new() { Timeout = 15_000 });
await Assertions.Expect(page.Locator("tr").Filter(new() { HasText = name }))
.ToHaveCountAsync(0, new() { Timeout = 10_000 });
}
@@ -123,6 +132,6 @@ public class NotificationListCrudTests
await page.Locator("button.btn-success:has-text('Save')").ClickAsync();
await Assertions.Expect(page.Locator("div.text-danger.small:has-text('Name required.')")).ToBeVisibleAsync();
Assert.Contains("/create", page.Url);
await Assertions.Expect(page).ToHaveURLAsync(new System.Text.RegularExpressions.Regex("/create"));
}
}