using ZB.MOM.WW.ScadaBridge.CentralUI.Services; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Services; /// /// Pins the pure logic behind the Create Instance page's Connection Bindings card /// (design 2026-08-21): Prefill from a root object, Object inference from a browser /// pick, and the binding list sent with Create. /// public class CreateBindingPlannerTests { private static IReadOnlyList Groups() => BindingGroupBuilder.Build( [ new BindingRow("Running", "Running", null, null), // (instance) new BindingRow("Left.MoveInFlag", "MoveInFlag", null, null), // bare default → suggest new BindingRow("Left.MoveOutFlag", "MoveOutFlag", null, null), new BindingRow("Recv.Count", "MESReceiver_023.Count", null, null), // prefixed default → from template new BindingRow("Recv.State", "MESReceiver_023.State", null, null), ]); /// Verifies that prefill fills blank objects only. [Fact] public void Prefill_fills_blank_objects_only() { var inputs = new Dictionary { ["Left"] = new(0, "Typed_Left"), }; var result = CreateBindingPlanner.Prefill(Groups(), inputs, connectionId: 7, rootObject: "Z28063"); Assert.Equal(new CreateBindingPlanner.GroupInput(7, "Z28063"), result[BindingGroupBuilder.InstanceGroupKey]); Assert.Equal(new CreateBindingPlanner.GroupInput(7, "Typed_Left"), result["Left"]); // typed wins Assert.Equal(new CreateBindingPlanner.GroupInput(7, "MESReceiver_023"), result["Recv"]); // from template Assert.Equal(CreateBindingPlanner.ObjectSource.Typed, CreateBindingPlanner.SourceOf(Groups()[1], result["Left"])); Assert.Equal(CreateBindingPlanner.ObjectSource.FromTemplate, CreateBindingPlanner.SourceOf(Groups()[2], result["Recv"])); } /// Verifies that prefill suggests root dot module for bare defaults. [Fact] public void Prefill_suggests_root_dot_module_for_bare_defaults() { var result = CreateBindingPlanner.Prefill(Groups(), new Dictionary(), 7, "Z28063"); Assert.Equal("Z28063.Left", result["Left"].Object); Assert.Equal(CreateBindingPlanner.ObjectSource.Suggested, CreateBindingPlanner.SourceOf(Groups()[1], result["Left"])); } /// Verifies that prefill with blank root sets connection only. [Fact] public void Prefill_with_blank_root_sets_connection_only() { var result = CreateBindingPlanner.Prefill(Groups(), new Dictionary(), 7, ""); Assert.Equal(new CreateBindingPlanner.GroupInput(7, null), result[BindingGroupBuilder.InstanceGroupKey]); Assert.Equal(new CreateBindingPlanner.GroupInput(7, null), result["Left"]); Assert.Equal(new CreateBindingPlanner.GroupInput(7, "MESReceiver_023"), result["Recv"]); } /// Verifies that object from pick strips member tail. /// The picked value for the case. /// The expected value for the case. [Theory] [InlineData("Z28063.Left.MoveInFlag", "Z28063.Left")] // leaf under the group → strip tail [InlineData("Z28063.Left", "Z28063.Left")] // object node → as-is [InlineData("ns=2;s=Plant.Left.MoveOutFlag", "ns=2;s=Plant.Left")] [InlineData("Other.Thing", "Other.Thing")] // no member tail matches → as-is public void ObjectFromPick_strips_member_tail(string picked, string expected) => Assert.Equal(expected, CreateBindingPlanner.ObjectFromPick(Groups()[1], picked)); /// Verifies that build bindings skips groups without connection or object. [Fact] public void BuildBindings_skips_groups_without_connection_or_object() { var inputs = new Dictionary { [BindingGroupBuilder.InstanceGroupKey] = new(7, "Z28063"), ["Left"] = new(7, null), // connection, no object → skipped (stays unbound) ["Recv"] = new(0, "MESReceiver_023"), // object, no connection → skipped }; var bindings = CreateBindingPlanner.BuildBindings(Groups(), inputs); var single = Assert.Single(bindings); Assert.Equal(("Running", 7, "Z28063.Running"), (single.AttributeName, single.DataConnectionId, single.DataSourceReferenceOverride)); } /// Verifies that build bindings rewrites every member of a bound group. [Fact] public void BuildBindings_rewrites_every_member_of_a_bound_group() { var inputs = new Dictionary { ["Left"] = new(7, "Z28063.Left") }; var bindings = CreateBindingPlanner.BuildBindings(Groups(), inputs); Assert.Equal(2, bindings.Count); Assert.Contains(bindings, b => b.AttributeName == "Left.MoveInFlag" && b.DataSourceReferenceOverride == "Z28063.Left.MoveInFlag"); } }