feat(adminui): editable S7 tag list via CollectionEditor
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Clusters.Drivers;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.S7;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests;
|
||||
@@ -95,7 +96,10 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
|
||||
var form = ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Clusters.Drivers
|
||||
.S7DriverPage.FormModel.FromOptions(opts);
|
||||
var roundTripped = form.ToOptions();
|
||||
var tagRows = opts.Tags
|
||||
.Select(ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Clusters.Drivers.S7DriverPage.S7TagRow.FromDefinition)
|
||||
.ToList();
|
||||
var roundTripped = form.ToOptions(tagRows.Select(r => r.ToDefinition()).ToList());
|
||||
|
||||
roundTripped.Host.ShouldBe("192.168.1.50");
|
||||
roundTripped.Port.ShouldBe(102);
|
||||
@@ -117,4 +121,94 @@ public sealed class S7DriverPageFormSerializationTests
|
||||
roundTripped.Tags[1].Name.ShouldBe("Status");
|
||||
roundTripped.Tags[1].Writable.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void S7TagRow_RoundTrip_PreservesEditableFields()
|
||||
{
|
||||
var def = new S7TagDefinition("Speed", "DB1.DBD0", S7DataType.Float32, Writable: true, StringLength: 80);
|
||||
|
||||
var row = S7DriverPage.S7TagRow.FromDefinition(def);
|
||||
var back = row.ToDefinition();
|
||||
|
||||
back.Name.ShouldBe("Speed");
|
||||
back.Address.ShouldBe("DB1.DBD0");
|
||||
back.DataType.ShouldBe(S7DataType.Float32);
|
||||
back.Writable.ShouldBeTrue();
|
||||
back.StringLength.ShouldBe(80);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void S7TagRow_CarriesThroughUneditedFields()
|
||||
{
|
||||
// WriteIdempotent is not exposed by the editor; it must survive FromDefinition→edit→ToDefinition.
|
||||
var def = new S7TagDefinition("Setpoint", "DB10.DBD0", S7DataType.Float32, Writable: true, WriteIdempotent: true);
|
||||
|
||||
var row = S7DriverPage.S7TagRow.FromDefinition(def);
|
||||
row.Name = "SetpointRenamed";
|
||||
row.Writable = false;
|
||||
var back = row.ToDefinition();
|
||||
|
||||
back.Name.ShouldBe("SetpointRenamed");
|
||||
back.Writable.ShouldBeFalse();
|
||||
// Un-edited field carried through via _source.
|
||||
back.WriteIdempotent.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void S7TagRow_ValidateRow_RejectsDuplicateNames()
|
||||
{
|
||||
var all = new List<S7DriverPage.S7TagRow>
|
||||
{
|
||||
S7DriverPage.S7TagRow.FromDefinition(new S7TagDefinition("Speed", "DB1.DBD0", S7DataType.Float32)),
|
||||
S7DriverPage.S7TagRow.FromDefinition(new S7TagDefinition("Status", "DB1.DBW4", S7DataType.Int16)),
|
||||
};
|
||||
|
||||
// Editing index 1 to a name that case-insensitively collides with index 0.
|
||||
var edited = all[1].Clone();
|
||||
edited.Name = "speed";
|
||||
S7DriverPage.S7TagRow.ValidateRow(edited, all, editIndex: 1)
|
||||
.ShouldBe("Duplicate tag name 'speed'.");
|
||||
|
||||
// Required-name guard.
|
||||
var blank = new S7DriverPage.S7TagRow();
|
||||
S7DriverPage.S7TagRow.ValidateRow(blank, all, editIndex: null)
|
||||
.ShouldBe("Name is required.");
|
||||
|
||||
// Unique name passes.
|
||||
var ok = all[1].Clone();
|
||||
ok.Name = "Torque";
|
||||
S7DriverPage.S7TagRow.ValidateRow(ok, all, editIndex: 1).ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TagList_SerializeRoundTrip_PreservesTags()
|
||||
{
|
||||
var opts = new S7DriverOptions
|
||||
{
|
||||
Host = "10.1.1.1",
|
||||
Tags =
|
||||
[
|
||||
new S7TagDefinition("Speed", "DB1.DBD0", S7DataType.Float32, Writable: true),
|
||||
new S7TagDefinition("Name", "DB2.DBB0", S7DataType.String, Writable: false, StringLength: 32),
|
||||
],
|
||||
};
|
||||
|
||||
var optsSkip = new JsonSerializerOptions(_opts)
|
||||
{
|
||||
UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
|
||||
};
|
||||
var json = JsonSerializer.Serialize(opts, optsSkip);
|
||||
var back = JsonSerializer.Deserialize<S7DriverOptions>(json, optsSkip);
|
||||
|
||||
back.ShouldNotBeNull();
|
||||
back.Tags.Count.ShouldBe(2);
|
||||
back.Tags[0].Name.ShouldBe("Speed");
|
||||
back.Tags[0].Address.ShouldBe("DB1.DBD0");
|
||||
back.Tags[0].DataType.ShouldBe(S7DataType.Float32);
|
||||
back.Tags[0].Writable.ShouldBeTrue();
|
||||
back.Tags[1].Name.ShouldBe("Name");
|
||||
back.Tags[1].DataType.ShouldBe(S7DataType.String);
|
||||
back.Tags[1].StringLength.ShouldBe(32);
|
||||
back.Tags[1].Writable.ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user