using System.Text.Json; using System.Text.Json.Serialization; using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests; /// /// Regression guard for the 2026-06-19 enum-serialization bug. The AdminUI S7 page now /// serialises as a STRING (its _jsonOpts gained a /// ). This proves the factory parses that AdminUI-shaped /// blob and round-trips the enum, and documents that the pre-fix NUMERIC form — which the old /// page emitted — threw because S7DriverConfigDto.CpuType is string?. /// public sealed class S7DriverConfigEnumSerializationTests { // Mirrors the (now fixed) AdminUI S7DriverPage._jsonOpts: camelCase + string enums. private static readonly JsonSerializerOptions _adminPageOpts = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter() }, }; /// Verifies the factory parses an AdminUI-authored (string-enum) S7 config and /// preserves the CpuType. [Fact] public void Factory_parses_admin_authored_string_enum_config() { var opts = new S7DriverOptions { Host = "10.0.0.5", Port = 102, CpuType = S7CpuType.S71500, Rack = 0, Slot = 1 }; var blob = JsonSerializer.Serialize(opts, _adminPageOpts); // The fixed AdminUI page must emit the enum as a string, not a number. blob.ShouldContain("\"cpuType\":\"S71500\""); var parsed = S7DriverFactoryExtensions.ParseOptions("s7-test", blob); parsed.CpuType.ShouldBe(S7CpuType.S71500); } /// Documents the original bug: the pre-fix AdminUI page emitted a numeric enum /// ("cpuType":40) which the string-typed config DTO cannot bind, so the factory throws. [Fact] public void Factory_throws_on_the_numeric_enum_form_the_pre_fix_page_emitted() { // 40 == (int)S7CpuType.S71500 — exactly what the pre-fix page (no converter) wrote for S71500. // The throw comes from binding a JSON number to the DTO's string? CpuType, so it fires for any number. const string numericBlob = "{\"host\":\"10.0.0.5\",\"port\":102,\"cpuType\":40,\"rack\":0,\"slot\":1}"; Should.Throw(() => S7DriverFactoryExtensions.ParseOptions("s7-test", numericBlob)); } }