using Microsoft.Extensions.Configuration; using ZB.MOM.WW.Configuration; namespace ZB.MOM.WW.Configuration.Tests; public sealed class ConfigPreflightTests { private static IConfiguration Config(Dictionary values) => new ConfigurationBuilder().AddInMemoryCollection(values).Build(); [Fact] public void Aggregates_all_failures() { var cfg = Config(new() { ["Node:Role"] = "Bogus", ["Node:RemotingPort"] = "0" }); var pf = ConfigPreflight.For(cfg) .Require("Node:Role", v => v is "Central" or "Site", "must be 'Central' or 'Site'") .RequirePort("Node:RemotingPort"); Assert.False(pf.IsValid); Assert.Equal(2, pf.Failures.Count); } [Fact] public void When_runs_block_only_if_condition_true() { var cfg = Config(new() { ["Node:Role"] = "Site" }); var pf = ConfigPreflight.For(cfg) .When(cfg["Node:Role"] == "Site", p => p.RequireValue("Node:SiteId")); Assert.False(pf.IsValid); // SiteId missing Assert.Contains(pf.Failures, f => f.Contains("Node:SiteId")); } [Fact] public void When_false_does_not_run_block() { var cfg = Config(new() { ["Node:Role"] = "Central" }); var pf = ConfigPreflight.For(cfg) .When(cfg["Node:Role"] == "Site", p => p.RequireValue("Node:SiteId")); Assert.True(pf.IsValid); // block skipped, no failure recorded } [Fact] public void ThrowIfInvalid_throws_aggregated_message() { var cfg = Config(new() { ["Node:Name"] = "" }); var ex = Assert.Throws(() => ConfigPreflight.For(cfg).RequireValue("Node:Name").ThrowIfInvalid()); Assert.StartsWith("Configuration validation failed:", ex.Message); Assert.Contains(" - Node:Name", ex.Message); } [Fact] public void ThrowIfInvalid_is_noop_when_valid() { var cfg = Config(new() { ["Node:Name"] = "ok" }); ConfigPreflight.For(cfg).RequireValue("Node:Name").ThrowIfInvalid(); // does not throw } }