using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Drivers; /// /// Closes deferment.md G-4. A guard already existed for DriverTypeNames ↔ the /raw /// driver PICKER, but not for the two dispatch maps downstream of it, so a driver could be registered, /// offered in the picker, and then have no config form — which is exactly what happened to /// Calculation (G-1) and to Sql/MTConnect/Calculation on the device modal (G-2). Both survived /// review because nothing could see them. /// These are ordinary map lookups rather than reflection over a private field: the two modals were /// converted from a Razor @switch — unreachable from a test, since it compiles into /// BuildRenderTree's IL — to DriverConfigFormMap / DeviceFormMap. There is no bUnit /// in this project, so a map is the only thing a test can hold on to. /// [Trait("Category", "Unit")] public sealed class DriverFormMapParityTests { /// Every declared driver type must have a typed config form. There is no exemption: a driver /// with no configurable surface still needs a form to say so, or the operator meets a bare warning. [Fact] public void Every_declared_driver_type_has_a_typed_config_form() { var missing = DriverTypeNames.All .Where(t => DriverConfigFormMap.Resolve(t) is null) .OrderBy(t => t, StringComparer.Ordinal) .ToList(); missing.ShouldBeEmpty( $"these driver types are registered and offered in the /raw picker but DriverConfigModal has no " + $"form for them, so their config is unauthorable through the UI: {string.Join(", ", missing)}"); } /// The reverse direction — a mapped type that is no longer a declared driver type is a stale /// entry, and would keep a deleted driver's form reachable. [Fact] public void Every_config_form_maps_to_a_declared_driver_type() { var declared = DriverTypeNames.All.ToHashSet(StringComparer.OrdinalIgnoreCase); var stale = DriverConfigFormMap.MappedDriverTypes .Where(t => !declared.Contains(t)) .OrderBy(t => t, StringComparer.Ordinal) .ToList(); stale.ShouldBeEmpty($"DriverConfigFormMap has entries for undeclared driver types: {string.Join(", ", stale)}"); } /// /// Every declared driver type must EITHER have a typed device form OR be declared single-connection. /// The either/or matters: demanding a device form from every driver would be wrong (Sql has one /// connection string, MTConnect one Agent URI, Calculation no connection at all), and a test that has /// to be suppressed for five drivers stops being read. Forcing the choice to be explicit is what makes /// this a guard — a new driver cannot silently fall through. /// [Fact] public void Every_declared_driver_type_has_a_device_form_or_is_declared_single_connection() { var unaccounted = DriverTypeNames.All .Where(t => DeviceFormMap.Resolve(t) is null && !DeviceFormMap.IsSingleConnection(t)) .OrderBy(t => t, StringComparer.Ordinal) .ToList(); unaccounted.ShouldBeEmpty( $"these driver types have neither a typed device form nor a place in " + $"DeviceFormMap.SingleConnectionDriverTypes, so DeviceModal falls through to its " + $"\"no typed device form\" warning: {string.Join(", ", unaccounted)}"); } /// The reverse direction for the device map. [Fact] public void Every_device_form_maps_to_a_declared_driver_type() { var declared = DriverTypeNames.All.ToHashSet(StringComparer.OrdinalIgnoreCase); var stale = DeviceFormMap.MappedDriverTypes .Concat(DeviceFormMap.SingleConnectionDriverTypes) .Where(t => !declared.Contains(t)) .Distinct(StringComparer.OrdinalIgnoreCase) .OrderBy(t => t, StringComparer.Ordinal) .ToList(); stale.ShouldBeEmpty($"DeviceFormMap references undeclared driver types: {string.Join(", ", stale)}"); } /// /// A driver that authors its connection on the DRIVER form must have a driver form to author it on. /// Without this, declaring a type single-connection would be a way to opt out of both maps at once /// and leave the connection unauthorable anywhere. /// [Fact] public void Every_single_connection_driver_has_a_driver_config_form() { var missing = DeviceFormMap.SingleConnectionDriverTypes .Where(t => DriverConfigFormMap.Resolve(t) is null) .OrderBy(t => t, StringComparer.Ordinal) .ToList(); missing.ShouldBeEmpty( $"these types are declared single-connection but have no driver config form, so their connection " + $"cannot be authored anywhere: {string.Join(", ", missing)}"); } }