using System.CommandLine; using ZB.MOM.WW.ScadaBridge.CLI.Commands; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; namespace ZB.MOM.WW.ScadaBridge.CLI.Tests.Commands; /// /// MV-11: the template attribute add / update commands must support /// structured multi-value (List) attributes — a new --element-type option, /// a JSON-array --value, client-side element-type validation, and /// / /// wired into the /// payload sent to the Management API. /// public class TemplateAttributeListTests { private static readonly Option Url = new("--url") { Recursive = true }; private static readonly Option Username = new("--username") { Recursive = true }; private static readonly Option Password = new("--password") { Recursive = true }; private static readonly Option Format = CliOptions.CreateFormatOption(); private static Command AttributeGroup() => TemplateCommands.Build(Url, Format, Username, Password) .Subcommands.Single(c => c.Name == "attribute"); // ---- option surface ---- [Fact] public void AttributeAdd_HasElementTypeOption() { var add = AttributeGroup().Subcommands.Single(c => c.Name == "add"); Assert.Contains("--element-type", add.Options.Select(o => o.Name)); } [Fact] public void AttributeUpdate_HasElementTypeOption() { var update = AttributeGroup().Subcommands.Single(c => c.Name == "update"); Assert.Contains("--element-type", update.Options.Select(o => o.Name)); } // ---- client-side element-type validation (both directions) ---- [Theory] [InlineData("String")] [InlineData("Int32")] [InlineData("Float")] [InlineData("Double")] [InlineData("Boolean")] [InlineData("DateTime")] public void ValidateElementType_ListWithValidScalar_Ok(string elementType) { var ok = TemplateCommands.TryValidateElementType("List", elementType, out var error); Assert.True(ok); Assert.Null(error); } [Fact] public void ValidateElementType_ListWithValidScalar_CaseInsensitive() { var ok = TemplateCommands.TryValidateElementType("List", "string", out var error); Assert.True(ok); Assert.Null(error); } [Fact] public void ValidateElementType_ListWithoutElementType_Error() { var ok = TemplateCommands.TryValidateElementType("List", null, out var error); Assert.False(ok); Assert.NotNull(error); } [Fact] public void ValidateElementType_ListWithBlankElementType_Error() { var ok = TemplateCommands.TryValidateElementType("List", " ", out var error); Assert.False(ok); Assert.NotNull(error); } [Fact] public void ValidateElementType_ListWithInvalidScalar_Error() { var ok = TemplateCommands.TryValidateElementType("List", "List", out var error); Assert.False(ok); Assert.NotNull(error); } [Fact] public void ValidateElementType_ListWithBinaryScalar_Error() { // Binary is a DataType but not a permitted List element scalar. var ok = TemplateCommands.TryValidateElementType("List", "Binary", out var error); Assert.False(ok); Assert.NotNull(error); } [Fact] public void ValidateElementType_ScalarWithElementType_Error() { var ok = TemplateCommands.TryValidateElementType("String", "Int32", out var error); Assert.False(ok); Assert.NotNull(error); } [Fact] public void ValidateElementType_ScalarWithoutElementType_Ok() { var ok = TemplateCommands.TryValidateElementType("Float", null, out var error); Assert.True(ok); Assert.Null(error); } // ---- payload wiring: the raw JSON value + ElementDataType flow into the command ---- [Fact] public void BuildAddCommand_ListAttribute_CarriesElementTypeAndRawJsonValue() { var cmd = TemplateCommands.BuildAddAttributeCommand( templateId: 7, name: "WorkOrders", dataType: "List", value: """["WO-1","WO-2"]""", description: null, dataSource: null, isLocked: false, elementType: "String"); Assert.Equal(7, cmd.TemplateId); Assert.Equal("List", cmd.DataType); Assert.Equal("String", cmd.ElementDataType); // The CLI forwards the raw JSON string unchanged — the API/codec parses it. Assert.Equal("""["WO-1","WO-2"]""", cmd.Value); } [Fact] public void BuildUpdateCommand_ListAttribute_CarriesElementTypeAndRawJsonValue() { var cmd = TemplateCommands.BuildUpdateAttributeCommand( attributeId: 42, name: "WorkOrders", dataType: "List", value: """["A","B"]""", description: null, dataSource: null, isLocked: false, elementType: "Int32"); Assert.Equal(42, cmd.AttributeId); Assert.Equal("List", cmd.DataType); Assert.Equal("Int32", cmd.ElementDataType); Assert.Equal("""["A","B"]""", cmd.Value); } [Fact] public void BuildAddCommand_ScalarAttribute_LeavesElementTypeNull() { var cmd = TemplateCommands.BuildAddAttributeCommand( templateId: 1, name: "Speed", dataType: "Float", value: "0", description: null, dataSource: null, isLocked: false, elementType: null); Assert.Null(cmd.ElementDataType); Assert.Equal("Float", cmd.DataType); } }