using Microsoft.Playwright; using ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.Cluster; namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.Monitoring; /// /// End-to-end guard for the Health dashboard KPI tiles (/monitoring/health). /// /// /// The Health dashboard fans out to three Akka cluster-singleton Asks every /// 10 s (Notification Outbox, Site Call, Audit) to populate nine KPI tiles. A /// previously-fixed bug caused those Asks to hang, leaving every tile showing /// the em-dash degrade placeholder () instead of a resolved numeric value. /// This test guards that regression: it asserts that every tile resolves to a value /// and never shows . /// /// /// /// The three tile groups and their selectors: /// /// /// Notification Outbox — inlined in Health.razor with no /// data-test attribute. Each is a Bootstrap div.card whose /// .card-body contains a value h3 and a small.text-muted /// label. Located by the card that contains the label text, then its h3. /// /// /// Audit — rendered by AuditKpiTiles.razor; each tile button /// carries a data-test attribute: audit-kpi-volume, /// audit-kpi-error-rate, audit-kpi-backlog. /// /// /// Site Calls — rendered by SiteCallKpiTiles.razor; each tile /// button carries a data-test attribute: site-call-kpi-buffered, /// site-call-kpi-stuck, site-call-kpi-parked. /// /// /// /// [Collection("Playwright")] public class HealthDashboardTests { private const string HealthUrl = "/monitoring/health"; /// /// The degrade placeholder rendered when a KPI loader faults — an em-dash /// (U+2014). A healthy tile shows a non-negative integer instead. /// private const string DegradePlaceholder = "—"; // — private readonly PlaywrightFixture _fixture; public HealthDashboardTests(PlaywrightFixture fixture) { _fixture = fixture; } /// /// Asserts that all nine KPI tiles on the Health dashboard resolve to numeric /// values and do not show the em-dash degrade placeholder (). /// /// /// A generous 20 s per-tile timeout is intentional: the tiles are populated /// asynchronously after initial render as the three singleton Asks /// complete. The Playwright web-first assertion retries within that window /// rather than using a fixed sleep, so a fast cluster will pass quickly. /// /// [SkippableFact] public async Task KpiTiles_ResolveToValues_NotDegradePlaceholder() { Skip.IfNot(await ClusterAvailability.IsAvailableAsync(), ClusterAvailability.SkipReason); var page = await _fixture.NewAuthenticatedPageAsync(); await page.GotoAsync($"{PlaywrightFixture.BaseUrl}{HealthUrl}"); await page.WaitForLoadStateAsync(LoadState.NetworkIdle); // ── Notification Outbox tiles (no data-test; inlined in Health.razor as // plain div.card elements, not buttons — use that to disambiguate from // the SiteCallKpiTiles which render their cards as