feat(adminui): B2-WP3 driver/device config modals + page-to-form refactor
Extract the 8 typed driver pages into embeddable <Driver>DriverForm bodies (channel/protocol config) and add per-driver <Driver>DeviceForm bodies (connection endpoint -> Device.DeviceConfig, v3 endpoint split). New DriverConfigModal + DeviceModal dispatch by DriverType (DriverTypeNames) for the /raw tree; Test-connect inside DeviceModal builds the merged Driver+Device config transiently via DriverDeviceConfigMerger. Routed pages now host the form bodies and keep working. Round-trip + enum-serialization guard tests for the Modbus driver form + Modbus device model; retargeted the existing page-form serialization tests + the _jsonOpts converter guard to the forms. Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
This commit is contained in:
+7
-6
@@ -3,13 +3,14 @@ using System.Text.Json.Serialization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Pages.Clusters.Drivers;
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Config;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests;
|
||||
|
||||
public sealed class GalaxyDriverPageFormSerializationTests
|
||||
{
|
||||
// Matches GalaxyDriverPage._jsonOpts (camelCase, no PropertyNameCaseInsensitive).
|
||||
// Matches GalaxyDriverForm._jsonOpts (camelCase, no PropertyNameCaseInsensitive).
|
||||
private static readonly JsonSerializerOptions _opts = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
@@ -142,7 +143,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
var driverOpts = JsonSerializer.Deserialize<GalaxyDriverOptions>(seededJson, _pageOpts);
|
||||
driverOpts.ShouldNotBeNull();
|
||||
|
||||
var form = GalaxyDriverPage.GalaxyFormModel.FromRecord(driverOpts!);
|
||||
var form = GalaxyDriverForm.GalaxyFormModel.FromRecord(driverOpts!);
|
||||
|
||||
// Assert REAL seeded values — not defaults.
|
||||
form.GatewayEndpoint.ShouldBe("http://10.100.0.48:5120");
|
||||
@@ -155,7 +156,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
|
||||
/// <summary>
|
||||
/// Defence-in-depth: a config that genuinely OMITS a section (no Reconnect key at all)
|
||||
/// must not throw — <see cref="GalaxyDriverPage.GalaxyFormModel.FromRecord"/> must
|
||||
/// must not throw — <see cref="GalaxyDriverForm.GalaxyFormModel.FromRecord"/> must
|
||||
/// null-coalesce the missing section to its default value.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
@@ -175,7 +176,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
driverOpts.ShouldNotBeNull();
|
||||
|
||||
// FromRecord must not throw even though Reconnect (and other sections) is null.
|
||||
var form = Should.NotThrow(() => GalaxyDriverPage.GalaxyFormModel.FromRecord(driverOpts!));
|
||||
var form = Should.NotThrow(() => GalaxyDriverForm.GalaxyFormModel.FromRecord(driverOpts!));
|
||||
|
||||
// Omitted Reconnect section falls back to GalaxyReconnectOptions() defaults.
|
||||
var defaultRc = new GalaxyReconnectOptions();
|
||||
@@ -185,7 +186,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Confirms that <see cref="GalaxyDriverPage.GalaxyFormModel.FromRecord"/> still
|
||||
/// Confirms that <see cref="GalaxyDriverForm.GalaxyFormModel.FromRecord"/> still
|
||||
/// round-trips correctly when all nested records are populated (non-regressed path).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
@@ -216,7 +217,7 @@ public sealed class GalaxyDriverPageFormSerializationTests
|
||||
ProbeTimeoutSeconds = 20,
|
||||
};
|
||||
|
||||
var form = GalaxyDriverPage.GalaxyFormModel.FromRecord(original);
|
||||
var form = GalaxyDriverForm.GalaxyFormModel.FromRecord(original);
|
||||
|
||||
form.GatewayEndpoint.ShouldBe("https://gw.example.com:5001");
|
||||
form.GatewayApiKeySecretRef.ShouldBe("env:MY_KEY");
|
||||
|
||||
Reference in New Issue
Block a user