+
Delete secret '@Name.Value'?
This tombstones the secret so the removal can propagate. The action is audited.
@if (_error is not null)
diff --git a/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Ui.Tests/ConfirmDeleteModalTests.cs b/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Ui.Tests/ConfirmDeleteModalTests.cs
index 775cf27..fd417be 100644
--- a/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Ui.Tests/ConfirmDeleteModalTests.cs
+++ b/ZB.MOM.WW.Secrets/tests/ZB.MOM.WW.Secrets.Ui.Tests/ConfirmDeleteModalTests.cs
@@ -34,7 +34,7 @@ public class ConfirmDeleteModalTests : TestContext
.Add(c => c.OnDeleted, () => deleted = true));
// The confirmation is a rendered in-page modal element.
- Assert.NotEmpty(cut.FindAll(".modal"));
+ Assert.NotEmpty(cut.FindAll(".zb-secrets-modal"));
Assert.Contains("db/primary", cut.Markup);
cut.Find("[data-testid=confirm-delete]").Click();
@@ -133,6 +133,59 @@ public class ConfirmDeleteModalTests : TestContext
.Add(c => c.Visible, false)
.Add(c => c.Name, name));
- Assert.Empty(cut.FindAll(".modal"));
+ Assert.Empty(cut.FindAll(".zb-secrets-modal"));
+ }
+
+ ///
+ /// scadaproj#2 regression pins. The modal previously used the bare modal class and
+ /// shipped no CSS, silently depending on the host having no opinion about it — Bootstrap 5's
+ /// .modal { display: none } made the overlay permanently invisible on every
+ /// Bootstrap host (ScadaBridge, OtOpcUa, HistorianGateway) while every handler kept working.
+ ///
+ [Fact]
+ public void ConfirmDeleteModal_UsesNoFrameworkReservedClassNames()
+ {
+ var cut = RenderVisibleModal();
+
+ // Bootstrap owns these selectors; any element carrying one is again at the mercy of
+ // whatever stylesheet the host happens to link.
+ string[] reserved = ["modal", "modal-title", "modal-backdrop", "modal-dialog", "modal-content"];
+ foreach (string cls in reserved)
+ {
+ Assert.Empty(cut.FindAll($".{cls}"));
+ }
+
+ // The elements themselves still render, under the component-scoped vocabulary.
+ Assert.NotEmpty(cut.FindAll(".zb-secrets-modal"));
+ Assert.NotEmpty(cut.FindAll(".zb-secrets-modal-backdrop"));
+ Assert.NotEmpty(cut.FindAll(".zb-secrets-modal-card"));
+ }
+
+ [Fact]
+ public void ConfirmDeleteModal_ShipsItsOwnStyles()
+ {
+ var cut = RenderVisibleModal();
+
+ // The RCL must carry the modal's CSS itself: no family host links a Secrets.Ui
+ // stylesheet, and three of the four never link a scoped-CSS bundle at all — so any
+ // styling delivered outside the component silently fails to load exactly like the
+ // original defect. The inline block must both position the overlay and give it a
+ // display mode, or a host reset/framework rule can hide it again.
+ var style = cut.FindAll("style").SingleOrDefault();
+ Assert.NotNull(style);
+ Assert.Contains(".zb-secrets-modal", style.TextContent);
+ Assert.Contains("position: fixed", style.TextContent);
+ Assert.Contains("display: flex", style.TextContent);
+ }
+
+ private IRenderedComponent
RenderVisibleModal()
+ {
+ Services.AddSingleton(new RecordingSecretStore());
+ Services.AddSingleton(new CapturingAuditWriter());
+ this.AddTestAuthorization().SetAuthorized("carol");
+
+ return RenderComponent(p => p
+ .Add(c => c.Visible, true)
+ .Add(c => c.Name, new SecretName("db/primary")));
}
}