feat(transport): normalize List attribute values to native JSON on import
This commit is contained in:
@@ -259,6 +259,122 @@ public sealed class EntitySerializerTests
|
||||
Assert.Equal("[\"a\",\"b\"]", rtAttr.Value);
|
||||
}
|
||||
|
||||
private static BundleContentDto MakeContentWithListAttribute(
|
||||
string value, DataType elementType)
|
||||
{
|
||||
var template = new TemplateDto(
|
||||
Name: "Pump",
|
||||
FolderName: null,
|
||||
BaseTemplateName: null,
|
||||
Description: null,
|
||||
Attributes: new[]
|
||||
{
|
||||
new TemplateAttributeDto(
|
||||
Name: "Tags",
|
||||
Value: value,
|
||||
DataType: DataType.List,
|
||||
IsLocked: false,
|
||||
Description: null,
|
||||
DataSourceReference: null,
|
||||
ElementDataType: elementType),
|
||||
},
|
||||
Alarms: Array.Empty<TemplateAlarmDto>(),
|
||||
Scripts: Array.Empty<TemplateScriptDto>(),
|
||||
Compositions: Array.Empty<TemplateCompositionDto>());
|
||||
|
||||
return new BundleContentDto(
|
||||
TemplateFolders: Array.Empty<TemplateFolderDto>(),
|
||||
Templates: new[] { template },
|
||||
SharedScripts: Array.Empty<SharedScriptDto>(),
|
||||
ExternalSystems: Array.Empty<ExternalSystemDto>(),
|
||||
DatabaseConnections: Array.Empty<DatabaseConnectionDto>(),
|
||||
NotificationLists: Array.Empty<NotificationListDto>(),
|
||||
SmtpConfigs: Array.Empty<SmtpConfigDto>(),
|
||||
ApiMethods: Array.Empty<ApiMethodDto>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Import_normalizes_old_form_Int32_list_value_to_native_json()
|
||||
{
|
||||
// Pre-native bundle: quoted Int32 list elements.
|
||||
var dto = MakeContentWithListAttribute("[\"10\",\"20\"]", DataType.Int32);
|
||||
|
||||
var aggregate = new EntitySerializer().FromBundleContent(dto);
|
||||
|
||||
var attr = Assert.Single(Assert.Single(aggregate.Templates).Attributes);
|
||||
Assert.Equal(DataType.List, attr.DataType);
|
||||
Assert.Equal(DataType.Int32, attr.ElementDataType);
|
||||
// Imported native: numbers unquoted.
|
||||
Assert.Equal("[10,20]", attr.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Import_leaves_string_list_value_quoted()
|
||||
{
|
||||
var dto = MakeContentWithListAttribute("[\"a\",\"b\"]", DataType.String);
|
||||
|
||||
var aggregate = new EntitySerializer().FromBundleContent(dto);
|
||||
|
||||
var attr = Assert.Single(Assert.Single(aggregate.Templates).Attributes);
|
||||
Assert.Equal(DataType.List, attr.DataType);
|
||||
Assert.Equal(DataType.String, attr.ElementDataType);
|
||||
// Strings stay quoted in native form.
|
||||
Assert.Equal("[\"a\",\"b\"]", attr.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Import_leaves_malformed_list_value_unchanged_without_throwing()
|
||||
{
|
||||
// Truncated JSON array — Decode throws FormatException; the import must
|
||||
// still succeed and carry the value through verbatim (DB normalizer is
|
||||
// the backstop).
|
||||
var dto = MakeContentWithListAttribute("[\"a\"", DataType.String);
|
||||
|
||||
var aggregate = new EntitySerializer().FromBundleContent(dto);
|
||||
|
||||
var attr = Assert.Single(Assert.Single(aggregate.Templates).Attributes);
|
||||
Assert.Equal("[\"a\"", attr.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Import_leaves_scalar_attribute_value_unchanged()
|
||||
{
|
||||
var template = new TemplateDto(
|
||||
Name: "Sensor",
|
||||
FolderName: null,
|
||||
BaseTemplateName: null,
|
||||
Description: null,
|
||||
Attributes: new[]
|
||||
{
|
||||
new TemplateAttributeDto(
|
||||
Name: "Pressure",
|
||||
Value: "42.0",
|
||||
DataType: DataType.Double,
|
||||
IsLocked: false,
|
||||
Description: null,
|
||||
DataSourceReference: null,
|
||||
ElementDataType: null),
|
||||
},
|
||||
Alarms: Array.Empty<TemplateAlarmDto>(),
|
||||
Scripts: Array.Empty<TemplateScriptDto>(),
|
||||
Compositions: Array.Empty<TemplateCompositionDto>());
|
||||
var dto = new BundleContentDto(
|
||||
TemplateFolders: Array.Empty<TemplateFolderDto>(),
|
||||
Templates: new[] { template },
|
||||
SharedScripts: Array.Empty<SharedScriptDto>(),
|
||||
ExternalSystems: Array.Empty<ExternalSystemDto>(),
|
||||
DatabaseConnections: Array.Empty<DatabaseConnectionDto>(),
|
||||
NotificationLists: Array.Empty<NotificationListDto>(),
|
||||
SmtpConfigs: Array.Empty<SmtpConfigDto>(),
|
||||
ApiMethods: Array.Empty<ApiMethodDto>());
|
||||
|
||||
var aggregate = new EntitySerializer().FromBundleContent(dto);
|
||||
|
||||
var attr = Assert.Single(Assert.Single(aggregate.Templates).Attributes);
|
||||
Assert.Equal(DataType.Double, attr.DataType);
|
||||
Assert.Equal("42.0", attr.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Roundtrip_scalar_attribute_with_null_ElementDataType_remains_null()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user