Expand XML docs across bridge and test code

This commit is contained in:
Joseph Doherty
2026-03-25 11:45:12 -04:00
parent 3f813b3869
commit 4833765606
86 changed files with 2323 additions and 0 deletions

View File

@@ -7,10 +7,16 @@ using ZB.MOM.WW.LmxOpcUa.Host.Status;
namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
{
/// <summary>
/// Verifies how the dashboard health service classifies bridge health from connection state and metrics.
/// </summary>
public class HealthCheckServiceTests
{
private readonly HealthCheckService _sut = new();
/// <summary>
/// Confirms that a disconnected runtime is reported as unhealthy.
/// </summary>
[Fact]
public void NotConnected_ReturnsUnhealthy()
{
@@ -20,6 +26,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
result.Message.ShouldContain("not connected");
}
/// <summary>
/// Confirms that a connected runtime with no metrics history is still considered healthy.
/// </summary>
[Fact]
public void Connected_NoMetrics_ReturnsHealthy()
{
@@ -28,6 +37,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
result.Color.ShouldBe("green");
}
/// <summary>
/// Confirms that good success-rate metrics keep the service in a healthy state.
/// </summary>
[Fact]
public void Connected_GoodMetrics_ReturnsHealthy()
{
@@ -39,6 +51,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
result.Status.ShouldBe("Healthy");
}
/// <summary>
/// Confirms that poor operation success rates degrade the reported health state.
/// </summary>
[Fact]
public void Connected_LowSuccessRate_ReturnsDegraded()
{
@@ -53,18 +68,27 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
result.Color.ShouldBe("yellow");
}
/// <summary>
/// Confirms that the boolean health helper reports true when the runtime is connected.
/// </summary>
[Fact]
public void IsHealthy_Connected_ReturnsTrue()
{
_sut.IsHealthy(ConnectionState.Connected, null).ShouldBe(true);
}
/// <summary>
/// Confirms that the boolean health helper reports false when the runtime is disconnected.
/// </summary>
[Fact]
public void IsHealthy_Disconnected_ReturnsFalse()
{
_sut.IsHealthy(ConnectionState.Disconnected, null).ShouldBe(false);
}
/// <summary>
/// Confirms that the error connection state is treated as unhealthy.
/// </summary>
[Fact]
public void Error_ReturnsUnhealthy()
{
@@ -72,6 +96,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
result.Status.ShouldBe("Unhealthy");
}
/// <summary>
/// Confirms that the reconnecting state is treated as unhealthy while recovery is in progress.
/// </summary>
[Fact]
public void Reconnecting_ReturnsUnhealthy()
{

View File

@@ -9,8 +9,14 @@ using ZB.MOM.WW.LmxOpcUa.Tests.Helpers;
namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
{
/// <summary>
/// Verifies the HTML, JSON, and health snapshots generated for the operator status dashboard.
/// </summary>
public class StatusReportServiceTests
{
/// <summary>
/// Confirms that the generated HTML contains every dashboard panel expected by operators.
/// </summary>
[Fact]
public void GenerateHtml_ContainsAllPanels()
{
@@ -25,6 +31,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("Footer");
}
/// <summary>
/// Confirms that the generated HTML includes the configured auto-refresh meta tag.
/// </summary>
[Fact]
public void GenerateHtml_ContainsMetaRefresh()
{
@@ -33,6 +42,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("meta http-equiv='refresh' content='10'");
}
/// <summary>
/// Confirms that the connection panel renders the current runtime connection state.
/// </summary>
[Fact]
public void GenerateHtml_ConnectionPanel_ShowsState()
{
@@ -41,6 +53,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("Connected");
}
/// <summary>
/// Confirms that the Galaxy panel renders the bridged Galaxy name.
/// </summary>
[Fact]
public void GenerateHtml_GalaxyPanel_ShowsName()
{
@@ -49,6 +64,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("TestGalaxy");
}
/// <summary>
/// Confirms that the operations table renders the expected performance metric headers.
/// </summary>
[Fact]
public void GenerateHtml_OperationsTable_ShowsHeaders()
{
@@ -62,6 +80,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("P95 (ms)");
}
/// <summary>
/// Confirms that the footer renders timestamp and version information.
/// </summary>
[Fact]
public void GenerateHtml_Footer_ContainsTimestampAndVersion()
{
@@ -71,6 +92,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
html.ShouldContain("Version:");
}
/// <summary>
/// Confirms that the generated JSON includes the major dashboard sections.
/// </summary>
[Fact]
public void GenerateJson_Deserializes()
{
@@ -86,6 +110,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
json.ShouldContain("Footer");
}
/// <summary>
/// Confirms that the report service reports healthy when the runtime connection is up.
/// </summary>
[Fact]
public void IsHealthy_WhenConnected_ReturnsTrue()
{
@@ -93,6 +120,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
sut.IsHealthy().ShouldBe(true);
}
/// <summary>
/// Confirms that the report service reports unhealthy when the runtime connection is down.
/// </summary>
[Fact]
public void IsHealthy_WhenDisconnected_ReturnsFalse()
{
@@ -102,6 +132,10 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
sut.IsHealthy().ShouldBe(false);
}
/// <summary>
/// Creates a status report service preloaded with representative runtime, Galaxy, and metrics data.
/// </summary>
/// <returns>A configured status report service for dashboard assertions.</returns>
private static StatusReportService CreateService()
{
var mxClient = new FakeMxAccessClient();

View File

@@ -9,12 +9,18 @@ using ZB.MOM.WW.LmxOpcUa.Tests.Helpers;
namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
{
/// <summary>
/// Verifies the lightweight HTTP dashboard host that exposes bridge status to operators.
/// </summary>
public class StatusWebServerTests : IDisposable
{
private readonly StatusWebServer _server;
private readonly HttpClient _client;
private readonly int _port;
/// <summary>
/// Starts a status web server on a random test port and prepares an HTTP client for endpoint assertions.
/// </summary>
public StatusWebServerTests()
{
_port = new Random().Next(18000, 19000);
@@ -26,12 +32,18 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
_client = new HttpClient { BaseAddress = new Uri($"http://localhost:{_port}") };
}
/// <summary>
/// Disposes the test HTTP client and stops the status web server.
/// </summary>
public void Dispose()
{
_client.Dispose();
_server.Dispose();
}
/// <summary>
/// Confirms that the dashboard root responds with HTML content.
/// </summary>
[Fact]
public async Task Root_ReturnsHtml200()
{
@@ -40,6 +52,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
response.Content.Headers.ContentType?.MediaType.ShouldBe("text/html");
}
/// <summary>
/// Confirms that the JSON status endpoint responds successfully.
/// </summary>
[Fact]
public async Task ApiStatus_ReturnsJson200()
{
@@ -48,6 +63,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
response.Content.Headers.ContentType?.MediaType.ShouldBe("application/json");
}
/// <summary>
/// Confirms that the health endpoint returns HTTP 200 when the bridge is healthy.
/// </summary>
[Fact]
public async Task ApiHealth_Returns200WhenHealthy()
{
@@ -58,6 +76,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
body.ShouldContain("healthy");
}
/// <summary>
/// Confirms that unknown dashboard routes return HTTP 404.
/// </summary>
[Fact]
public async Task UnknownPath_Returns404()
{
@@ -65,6 +86,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
response.StatusCode.ShouldBe(HttpStatusCode.NotFound);
}
/// <summary>
/// Confirms that unsupported HTTP methods are rejected with HTTP 405.
/// </summary>
[Fact]
public async Task PostMethod_Returns405()
{
@@ -72,6 +96,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
response.StatusCode.ShouldBe(HttpStatusCode.MethodNotAllowed);
}
/// <summary>
/// Confirms that cache-control headers disable caching for dashboard responses.
/// </summary>
[Fact]
public async Task CacheHeaders_Present()
{
@@ -80,6 +107,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Status
response.Headers.CacheControl?.NoStore.ShouldBe(true);
}
/// <summary>
/// Confirms that the server can be started and stopped cleanly.
/// </summary>
[Fact]
public void StartStop_DoesNotThrow()
{