Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Components/OpcUaEndpointVerifyTests.cs
T

96 lines
4.0 KiB
C#

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;
/// <summary>
/// Covers the M7-B8 (T17) "Verify endpoint" affordance added to
/// <see cref="OpcUaEndpointEditor"/>: a button that calls the injected
/// <see cref="IEndpointVerificationService"/> with the current endpoint config and
/// renders the typed <see cref="VerifyEndpointResult"/> — green on success, a red
/// failure line otherwise, and a read-only certificate panel when the failure is
/// <see cref="VerifyFailureKind.UntrustedCertificate"/> with a captured cert.
/// </summary>
public class OpcUaEndpointVerifyTests : BunitContext
{
private readonly IEndpointVerificationService _verify =
Substitute.For<IEndpointVerificationService>();
public OpcUaEndpointVerifyTests()
{
Services.AddSingleton(_verify);
}
private IRenderedComponent<OpcUaEndpointEditor> RenderEditor() =>
Render<OpcUaEndpointEditor>(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<string>(), Arg.Any<string>(), Arg.Any<string>(),
Arg.Any<OpcUaEndpointConfig>(), Arg.Any<CancellationToken>())
.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<string>(), Arg.Any<string>(), Arg.Any<string>(),
Arg.Any<OpcUaEndpointConfig>(), Arg.Any<CancellationToken>())
.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<string>(), Arg.Any<string>(), Arg.Any<string>(),
Arg.Any<OpcUaEndpointConfig>(), Arg.Any<CancellationToken>())
.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]"));
}
}