Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.IntegrationTests/StartupValidationTests.cs
T
Joseph Doherty 513fa1aa16 docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)
Comment/XML-doc changes only:
- add summaries to ~10k test methods, fixtures, fakes and helpers
  (+ <param> on theories, <returns> on async Task methods,
  <inheritdoc/> on interface implementations the checker can resolve)
- strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N,
  #NN, Component-0NN) from comments, keeping the explanatory text;
  reword false positives in comments only
- real docs on fakes implementing BCL/library interfaces
  (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime)
- reword the last 5 src/ false positives (CWE-1236, failures-1,
  year-0001, M365)

Only non-comment edits: four one-line nested classes split across lines
so members can carry docs. Build 0 errors / 0 warnings.
2026-10-07 15:05:49 -04:00

137 lines
5.7 KiB
C#

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
namespace ZB.MOM.WW.ScadaBridge.IntegrationTests;
/// <summary>
/// Startup validation — missing required config fails with clear error.
/// Tests the StartupValidator that runs on boot.
///
/// Note: These tests temporarily set environment variables because Program.cs reads
/// configuration from env vars in the initial ConfigurationBuilder (before WebApplicationFactory
/// can inject settings). Each test saves/restores env vars to avoid interference.
/// </summary>
public class StartupValidationTests
{
/// <summary>Verifies that a missing role throws an InvalidOperationException.</summary>
[Fact]
public void MissingRole_ThrowsInvalidOperationException()
{
// Set all required config EXCEPT Role
using var env = new TempEnvironment(new Dictionary<string, string>
{
["DOTNET_ENVIRONMENT"] = "Development",
["ScadaBridge__Node__NodeHostname"] = "localhost",
["ScadaBridge__Node__RemotingPort"] = "8081",
["ScadaBridge__Cluster__SeedNodes__0"] = "akka.tcp://scadabridge@localhost:8081",
["ScadaBridge__Cluster__SeedNodes__1"] = "akka.tcp://scadabridge@localhost:8082",
});
var factory = new WebApplicationFactory<Program>();
var ex = Assert.Throws<InvalidOperationException>(() => factory.CreateClient());
Assert.Contains("Role", ex.Message, StringComparison.OrdinalIgnoreCase);
factory.Dispose();
}
/// <summary>Verifies that a missing JWT signing key for the Central role throws an InvalidOperationException.</summary>
[Fact]
public void MissingJwtSigningKey_ForCentral_ThrowsInvalidOperationException()
{
using var env = new TempEnvironment(new Dictionary<string, string>
{
["DOTNET_ENVIRONMENT"] = "Development",
["ScadaBridge__Node__Role"] = "Central",
["ScadaBridge__Node__NodeHostname"] = "localhost",
["ScadaBridge__Node__RemotingPort"] = "8081",
["ScadaBridge__Cluster__SeedNodes__0"] = "akka.tcp://scadabridge@localhost:8081",
["ScadaBridge__Cluster__SeedNodes__1"] = "akka.tcp://scadabridge@localhost:8082",
["ScadaBridge__Database__ConfigurationDb"] = "Server=x;Database=x",
["ScadaBridge__Database__MachineDataDb"] = "Server=x;Database=x",
["ScadaBridge__Security__Ldap__Server"] = "localhost",
// Deliberately missing JwtSigningKey
});
var factory = new WebApplicationFactory<Program>();
var ex = Assert.Throws<InvalidOperationException>(() => factory.CreateClient());
Assert.Contains("JwtSigningKey", ex.Message, StringComparison.OrdinalIgnoreCase);
factory.Dispose();
}
/// <summary>Verifies that the Central role starts successfully with a valid configuration.</summary>
[Fact]
public void CentralRole_StartsSuccessfully_WithValidConfig()
{
using var factory = new ScadaBridgeWebApplicationFactory();
using var client = factory.CreateClient();
Assert.NotNull(client);
}
/// <summary>
/// Helper to temporarily set environment variables and restore them on dispose.
/// Clears all ScadaBridge__ vars first to ensure a clean slate.
/// </summary>
private sealed class TempEnvironment : IDisposable
{
private readonly Dictionary<string, string?> _previousValues = new();
/// <summary>
/// All ScadaBridge env vars that might be set by other tests/factories.
/// </summary>
private static readonly string[] KnownKeys =
{
"DOTNET_ENVIRONMENT",
"ScadaBridge__Node__Role",
"ScadaBridge__Node__NodeHostname",
"ScadaBridge__Node__RemotingPort",
"ScadaBridge__Node__SiteId",
"ScadaBridge__Cluster__SeedNodes__0",
"ScadaBridge__Cluster__SeedNodes__1",
"ScadaBridge__Database__ConfigurationDb",
"ScadaBridge__Database__MachineDataDb",
"ScadaBridge__Database__SkipMigrations",
"ScadaBridge__Security__JwtSigningKey",
"ScadaBridge__Security__Ldap__Server",
"ScadaBridge__Security__Ldap__Port",
"ScadaBridge__Security__Ldap__Transport",
"ScadaBridge__Security__Ldap__AllowInsecure",
"ScadaBridge__Security__Ldap__SearchBase",
"ScadaBridge__Security__Ldap__ServiceAccountDn",
"ScadaBridge__Security__Ldap__ServiceAccountPassword",
};
/// <summary>Sets the given environment variables, remembering the prior values so they can be restored.</summary>
/// <param name="varsToSet">The environment variables to set.</param>
public TempEnvironment(Dictionary<string, string> varsToSet)
{
// Save and clear all known keys
foreach (var key in KnownKeys)
{
_previousValues[key] = Environment.GetEnvironmentVariable(key);
Environment.SetEnvironmentVariable(key, null);
}
// Set the requested vars
foreach (var (key, value) in varsToSet)
{
if (!_previousValues.ContainsKey(key))
_previousValues[key] = Environment.GetEnvironmentVariable(key);
Environment.SetEnvironmentVariable(key, value);
}
}
/// <summary>Releases the resources held by this test class.</summary>
public void Dispose()
{
foreach (var (key, previousValue) in _previousValues)
{
Environment.SetEnvironmentVariable(key, previousValue);
}
}
}
}