feat(transport): round-trip ElementDataType for List attributes
Add DataType? ElementDataType to TemplateAttributeDto (optional, default null for backward-compat with old bundles). Map it in both directions in EntitySerializer (export + FromBundleContent) and in all three TemplateAttribute construction sites in BundleImporter (BuildTemplate, SyncTemplateAttributesAsync add-path, and SyncTemplateAttributesAsync update-path including change-detection). Two new round-trip tests in EntitySerializerTests confirm List attributes survive export→import and that old DTOs with null ElementDataType import cleanly.
This commit is contained in:
@@ -223,4 +223,71 @@ public sealed class EntitySerializerTests
|
||||
var sys = Assert.Single(aggregate.ExternalSystems);
|
||||
Assert.Null(sys.AuthConfiguration);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Roundtrip_List_attribute_preserves_ElementDataType()
|
||||
{
|
||||
// A template with a DataType.List attribute whose element type is String.
|
||||
var template = new Template("Pump") { Id = 1 };
|
||||
template.Attributes.Add(new TemplateAttribute("Tags")
|
||||
{
|
||||
Id = 1,
|
||||
TemplateId = 1,
|
||||
DataType = DataType.List,
|
||||
ElementDataType = DataType.String,
|
||||
Value = "[\"a\",\"b\"]",
|
||||
IsLocked = false,
|
||||
});
|
||||
|
||||
var aggregate = MakeEmptyAggregate() with { Templates = new[] { template } };
|
||||
|
||||
var sut = new EntitySerializer();
|
||||
var dto = sut.ToBundleContent(aggregate);
|
||||
|
||||
// Export side: DTO must carry ElementDataType.
|
||||
var dtoTemplate = Assert.Single(dto.Templates);
|
||||
var dtoAttr = Assert.Single(dtoTemplate.Attributes);
|
||||
Assert.Equal(DataType.List, dtoAttr.DataType);
|
||||
Assert.Equal(DataType.String, dtoAttr.ElementDataType);
|
||||
|
||||
// Import side: entity reconstructed from DTO preserves the value.
|
||||
var roundTripped = sut.FromBundleContent(dto);
|
||||
var rtTemplate = Assert.Single(roundTripped.Templates);
|
||||
var rtAttr = Assert.Single(rtTemplate.Attributes);
|
||||
Assert.Equal(DataType.List, rtAttr.DataType);
|
||||
Assert.Equal(DataType.String, rtAttr.ElementDataType);
|
||||
Assert.Equal("[\"a\",\"b\"]", rtAttr.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Roundtrip_scalar_attribute_with_null_ElementDataType_remains_null()
|
||||
{
|
||||
// Backward-compat: an old bundle DTO with null ElementDataType must not throw
|
||||
// and must produce a scalar attribute with null ElementDataType.
|
||||
var template = new Template("Sensor") { Id = 1 };
|
||||
template.Attributes.Add(new TemplateAttribute("Pressure")
|
||||
{
|
||||
Id = 1,
|
||||
TemplateId = 1,
|
||||
DataType = DataType.Double,
|
||||
ElementDataType = null,
|
||||
Value = "42.0",
|
||||
IsLocked = false,
|
||||
});
|
||||
|
||||
var aggregate = MakeEmptyAggregate() with { Templates = new[] { template } };
|
||||
|
||||
var sut = new EntitySerializer();
|
||||
var dto = sut.ToBundleContent(aggregate);
|
||||
|
||||
var dtoTemplate = Assert.Single(dto.Templates);
|
||||
var dtoAttr = Assert.Single(dtoTemplate.Attributes);
|
||||
Assert.Equal(DataType.Double, dtoAttr.DataType);
|
||||
Assert.Null(dtoAttr.ElementDataType);
|
||||
|
||||
var roundTripped = sut.FromBundleContent(dto);
|
||||
var rtAttr = Assert.Single(Assert.Single(roundTripped.Templates).Attributes);
|
||||
Assert.Equal(DataType.Double, rtAttr.DataType);
|
||||
Assert.Null(rtAttr.ElementDataType);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user