using Bunit; using Microsoft.Extensions.DependencyInjection; using NSubstitute; using ZB.MOM.WW.ScadaBridge.CentralUI.Components.Forms; using ZB.MOM.WW.ScadaBridge.CentralUI.Services; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; using ZB.MOM.WW.ScadaBridge.Commons.Types.DataConnections; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Components; /// /// Covers the M7-B8 (T17) "Verify endpoint" affordance added to /// : a button that calls the injected /// with the current endpoint config and /// renders the typed — green on success, a red /// failure line otherwise, and a read-only certificate panel when the failure is /// with a captured cert. /// public class OpcUaEndpointVerifyTests : BunitContext { private readonly IEndpointVerificationService _verify = Substitute.For(); public OpcUaEndpointVerifyTests() { Services.AddSingleton(_verify); } private IRenderedComponent RenderEditor() => Render(p => p .Add(c => c.Config, new OpcUaEndpointConfig { EndpointUrl = "opc.tcp://host:4840" }) .Add(c => c.SiteIdentifier, "plant-a") .Add(c => c.ConnectionName, "PLC-OPC") .Add(c => c.Protocol, "OpcUa")); [Fact] public void Verify_Success_ShowsSuccessMessage() { _verify.VerifyAsync( Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) .Returns(new VerifyEndpointResult(true, null, null, null)); var cut = RenderEditor(); cut.Find("[data-test=verify-endpoint-btn]").Click(); Assert.NotEmpty(cut.FindAll("[data-test=verify-success]")); Assert.Empty(cut.FindAll("[data-test=verify-failure]")); Assert.Empty(cut.FindAll("[data-test=verify-cert-panel]")); } [Fact] public void Verify_UntrustedCertificate_ShowsCertPanelWithThumbprint() { var cert = new ServerCertInfo( Thumbprint: "ABCDEF0123456789", Subject: "CN=opc-server", Issuer: "CN=opc-server", NotBeforeUtc: new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), NotAfterUtc: new DateTime(2027, 1, 1, 0, 0, 0, DateTimeKind.Utc), DerBase64: "ZGVy"); _verify.VerifyAsync( Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) .Returns(new VerifyEndpointResult( false, VerifyFailureKind.UntrustedCertificate, "Untrusted certificate.", cert)); var cut = RenderEditor(); cut.Find("[data-test=verify-endpoint-btn]").Click(); var panel = cut.Find("[data-test=verify-cert-panel]"); Assert.Contains("ABCDEF0123456789", panel.TextContent); Assert.Contains("CN=opc-server", panel.TextContent); // The failure line is still shown alongside the cert panel. Assert.NotEmpty(cut.FindAll("[data-test=verify-failure]")); } [Fact] public void Verify_GenericFailure_ShowsFailureMessage() { _verify.VerifyAsync( Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) .Returns(new VerifyEndpointResult( false, VerifyFailureKind.Unreachable, "Connection refused.", null)); var cut = RenderEditor(); cut.Find("[data-test=verify-endpoint-btn]").Click(); var failure = cut.Find("[data-test=verify-failure]"); Assert.Contains("Connection refused.", failure.TextContent); Assert.Empty(cut.FindAll("[data-test=verify-success]")); Assert.Empty(cut.FindAll("[data-test=verify-cert-panel]")); } }