diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/HealthDashboardTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/HealthDashboardTests.cs
new file mode 100644
index 00000000..26ab2fcf
--- /dev/null
+++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Monitoring/HealthDashboardTests.cs
@@ -0,0 +1,149 @@
+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