513fa1aa16
Comment/XML-doc changes only: - add summaries to ~10k test methods, fixtures, fakes and helpers (+ <param> on theories, <returns> on async Task methods, <inheritdoc/> on interface implementations the checker can resolve) - strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N, #NN, Component-0NN) from comments, keeping the explanatory text; reword false positives in comments only - real docs on fakes implementing BCL/library interfaces (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime) - reword the last 5 src/ false positives (CWE-1236, failures-1, year-0001, M365) Only non-comment edits: four one-line nested classes split across lines so members can carry docs. Build 0 errors / 0 warnings.
187 lines
7.2 KiB
C#
187 lines
7.2 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>
|
|
/// 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 ----
|
|
|
|
/// <summary>Verifies that the attribute add command exposes an element-type option.</summary>
|
|
[Fact]
|
|
public void AttributeAdd_HasElementTypeOption()
|
|
{
|
|
var add = AttributeGroup().Subcommands.Single(c => c.Name == "add");
|
|
Assert.Contains("--element-type", add.Options.Select(o => o.Name));
|
|
}
|
|
|
|
/// <summary>Verifies that the attribute update command exposes an element-type option.</summary>
|
|
[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) ----
|
|
|
|
/// <summary>Verifies that a List attribute with a valid scalar element type passes validation.</summary>
|
|
/// <param name="elementType">The scalar element type name under test.</param>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Verifies that element-type validation for a List attribute is case-insensitive.</summary>
|
|
[Fact]
|
|
public void ValidateElementType_ListWithValidScalar_CaseInsensitive()
|
|
{
|
|
var ok = TemplateCommands.TryValidateElementType("List", "string", out var error);
|
|
Assert.True(ok);
|
|
Assert.Null(error);
|
|
}
|
|
|
|
/// <summary>Verifies that a List attribute without an element type fails validation.</summary>
|
|
[Fact]
|
|
public void ValidateElementType_ListWithoutElementType_Error()
|
|
{
|
|
var ok = TemplateCommands.TryValidateElementType("List", null, out var error);
|
|
Assert.False(ok);
|
|
Assert.NotNull(error);
|
|
}
|
|
|
|
/// <summary>Verifies that a List attribute with a blank element type fails validation.</summary>
|
|
[Fact]
|
|
public void ValidateElementType_ListWithBlankElementType_Error()
|
|
{
|
|
var ok = TemplateCommands.TryValidateElementType("List", " ", out var error);
|
|
Assert.False(ok);
|
|
Assert.NotNull(error);
|
|
}
|
|
|
|
/// <summary>Verifies that a List attribute with an invalid scalar element type fails validation.</summary>
|
|
[Fact]
|
|
public void ValidateElementType_ListWithInvalidScalar_Error()
|
|
{
|
|
var ok = TemplateCommands.TryValidateElementType("List", "List", out var error);
|
|
Assert.False(ok);
|
|
Assert.NotNull(error);
|
|
}
|
|
|
|
/// <summary>Verifies that a List attribute with a binary element type fails validation.</summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Verifies that a scalar attribute with an element type fails validation.</summary>
|
|
[Fact]
|
|
public void ValidateElementType_ScalarWithElementType_Error()
|
|
{
|
|
var ok = TemplateCommands.TryValidateElementType("String", "Int32", out var error);
|
|
Assert.False(ok);
|
|
Assert.NotNull(error);
|
|
}
|
|
|
|
/// <summary>Verifies that a scalar attribute without an element type passes validation.</summary>
|
|
[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 ----
|
|
|
|
/// <summary>Verifies that building an add command for a List attribute carries the element type and the raw JSON value.</summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Verifies that building an update command for a List attribute carries the element type and the raw JSON value.</summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Verifies that building an add command for a scalar attribute leaves the element type null.</summary>
|
|
[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);
|
|
}
|
|
}
|