173 lines
5.7 KiB
C#
173 lines
5.7 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// MV-11: the <c>template attribute add</c> / <c>update</c> commands must support
|
|
/// structured multi-value (List) attributes — a new <c>--element-type</c> option,
|
|
/// a JSON-array <c>--value</c>, client-side element-type validation, and
|
|
/// <see cref="AddTemplateAttributeCommand.ElementDataType"/> /
|
|
/// <see cref="UpdateTemplateAttributeCommand.ElementDataType"/> wired into the
|
|
/// payload sent to the Management API.
|
|
/// </summary>
|
|
public class TemplateAttributeListTests
|
|
{
|
|
private static readonly Option<string> Url = new("--url") { Recursive = true };
|
|
private static readonly Option<string> Username = new("--username") { Recursive = true };
|
|
private static readonly Option<string> Password = new("--password") { Recursive = true };
|
|
private static readonly Option<string> 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);
|
|
}
|
|
}
|