diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/SiteCalls/SiteCallsPageTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/SiteCalls/SiteCallsPageTests.cs
index a53837ea..0ff7d3fc 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/SiteCalls/SiteCallsPageTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/SiteCalls/SiteCallsPageTests.cs
@@ -30,6 +30,9 @@ namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests.SiteCalls;
/// rows, never on Failed (or other) rows.
/// - RetryClickThrough — clicking Retry on a Parked row confirms
/// the dialog, relays to the owning site, and surfaces an outcome toast.
+/// - DiscardClickThrough — clicking Discard on a Parked row confirms
+/// the danger dialog ("Delete"), relays to the owning site, and surfaces an
+/// outcome toast.
///
///
///
@@ -328,4 +331,60 @@ public class SiteCallsPageTests
await SiteCallDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
}
}
+
+ ///
+ /// Mirrors
+ /// but exercises the Discard path: clicking Discard opens a danger
+ /// confirm modal (Dialog.ConfirmAsync with danger: true), whose footer
+ /// button is labelled "Delete" (not "Confirm"). Confirming relays a discard to
+ /// the owning site and ShowRelayOutcome surfaces exactly one outcome toast.
+ ///
+ [SkippableFact]
+ public async Task DiscardClickThrough_OnParkedRow_ConfirmsRelayAndShowsOutcomeToast()
+ {
+ Skip.IfNot(await SiteCallDataSeeder.IsAvailableAsync(), DbUnavailableSkipReason);
+
+ var runId = Guid.NewGuid().ToString("N");
+ var targetPrefix = $"playwright-test/sc-discard-click/{runId}/";
+ var parkedId = Guid.NewGuid();
+ var now = DateTime.UtcNow;
+
+ try
+ {
+ // Parked + real site-a so the discard relay resolves fast (NotParked ack for this
+ // freshly-seeded GUID), surfacing a toast.
+ await SiteCallDataSeeder.InsertSiteCallAsync(
+ trackedOperationId: parkedId, channel: "ApiOutbound", target: targetPrefix + "parked",
+ sourceSite: "site-a", status: "Parked", retryCount: 3,
+ lastError: "HTTP 503 from ERP", httpStatus: 503,
+ createdAtUtc: now, updatedAtUtc: now);
+
+ var page = await _fixture.NewAuthenticatedPageAsync();
+ await page.GotoAsync($"{PlaywrightFixture.BaseUrl}{SiteCallsUrl}");
+ await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
+
+ await SetSearchKeywordAsync(page, targetPrefix + "parked");
+ await page.Locator("[data-test='site-calls-query']").ClickAsync();
+ await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
+
+ var parkedRow = page.Locator("tbody tr", new() { HasText = targetPrefix + "parked" });
+ await Assertions.Expect(parkedRow).ToBeVisibleAsync();
+
+ // Discard opens the danger confirm modal.
+ await parkedRow.Locator("button:has-text('Discard')").ClickAsync();
+
+ // Danger confirm — labelled "Delete" (Dialog.ConfirmAsync(..., danger: true)).
+ var deleteButton = page.Locator(".modal-footer .btn-danger");
+ await Assertions.Expect(deleteButton).ToBeVisibleAsync();
+ await Assertions.Expect(deleteButton).ToHaveTextAsync("Delete");
+ await deleteButton.ClickAsync();
+
+ // One outcome toast (Applied / NotParked / SiteUnreachable — tolerant).
+ await Assertions.Expect(page.Locator(".toast")).ToHaveCountAsync(1, new() { Timeout = 15_000 });
+ }
+ finally
+ {
+ await SiteCallDataSeeder.DeleteByTargetPrefixAsync(targetPrefix);
+ }
+ }
}