From 9c36036f2a4850bdbf2e40d7908e1c476c68c36f Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 6 Jun 2026 14:47:25 -0400 Subject: [PATCH] test(playwright): make EventLogs query-completion deterministic (review fix) --- .../Monitoring/EventLogsTests.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/EventLogsTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/EventLogsTests.cs index c1df6f76..7e85dee1 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/EventLogsTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/EventLogsTests.cs @@ -85,15 +85,24 @@ public class EventLogsTests await page.GotoAsync($"{PlaywrightFixture.BaseUrl}{EventLogsUrl}"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); - await page.Locator("#filter-site").SelectOptionAsync(new SelectOptionValue { Value = "site-a" }); - await page.Locator("button.btn.btn-primary.btn-sm:has-text('Search')").ClickAsync(); + await Assertions.Expect(page.Locator("h4:has-text('Site Event Logs')")).ToBeVisibleAsync(); - // The query resolved once the results table renders. The empty-state is itself a - // No events found., so a data row OR the empty-state - // row both surface under table tbody tr. Generous timeout: the fetch is an Akka - // Ask round-trip to a live site. - var settled = page.Locator("table tbody tr, td:has-text('No events found.')"); - await Assertions.Expect(settled.First).ToBeVisibleAsync(new() { Timeout = 15_000 }); + await page.Locator("#filter-site").SelectOptionAsync(new SelectOptionValue { Value = "site-a" }); + var searchBtn = page.Locator("button.btn.btn-primary.btn-sm:has-text('Search')"); + await searchBtn.ClickAsync(); + + // The Search button re-enables only when _searching flips back to false, i.e. after the + // site's Akka Ask round-trip completes. Gating on it here makes the table assertion below a + // genuine post-query check (a hung Ask fails here instead of false-passing on the + // intermediate empty render Blazor flushes while _entries is a momentary empty list). + await Assertions.Expect(searchBtn).ToBeEnabledAsync(new() { Timeout = 15_000 }); + + // The query has completed (Search re-enabled above), so the terminal table render is now + // present: a data row OR the empty-state row. The empty-state markup is itself a + // No events found. living inside table tbody, so "table tbody + // tr" matches it whether or not the site has events. + var settled = page.Locator("table tbody tr"); + await Assertions.Expect(settled.First).ToBeVisibleAsync(new() { Timeout = 5_000 }); // Exercise the row-expand ONLY IF real data rows exist. A clean site may have zero // logged events, and event logs are not seedable from central — so when no expand