using CliFx.Attributes; using CliFx.Infrastructure; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.FOCAS; namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli.Tests; /// /// Covers — the pure, deterministic mapping /// from the base's CNC host/port/series/timeout flags onto a /// FocasDriverOptions. The CLI is one-shot so the background connectivity probe /// must be disabled. /// [Trait("Category", "Unit")] public sealed class FocasCommandBaseBuildOptionsTests { [Command("noop-test", Description = "Test-only probe of FocasCommandBase.BuildOptions.")] private sealed class ProbeOnly : FocasCommandBase { public override ValueTask ExecuteAsync(IConsole console) => default; public FocasDriverOptions Invoke(IReadOnlyList tags) => BuildOptions(tags); } [Fact] public void BuildOptions_disables_probe_for_one_shot_cli_runs() { var sut = new ProbeOnly { CncHost = "10.0.0.5", CncPort = 8193, Series = FocasCncSeries.ThirtyOne_i, TimeoutMs = 5000, }; var options = sut.Invoke([]); options.Probe.ShouldNotBeNull(); options.Probe.Enabled.ShouldBeFalse(); } [Fact] public void BuildOptions_maps_TimeoutMs_to_Timeout_TimeSpan() { var sut = new ProbeOnly { CncHost = "h", TimeoutMs = 7500 }; var options = sut.Invoke([]); options.Timeout.ShouldBe(TimeSpan.FromMilliseconds(7500)); } [Fact] public void BuildOptions_flows_host_port_series_through() { var sut = new ProbeOnly { CncHost = "cnc.shop.local", CncPort = 8194, Series = FocasCncSeries.Zero_i_F, TimeoutMs = 3000, }; var options = sut.Invoke([]); options.Devices.Count.ShouldBe(1); options.Devices[0].HostAddress.ShouldBe("focas://cnc.shop.local:8194"); options.Devices[0].Series.ShouldBe(FocasCncSeries.Zero_i_F); } [Fact] public void BuildOptions_forwards_tag_list_verbatim() { var sut = new ProbeOnly { CncHost = "h" }; var tag = new FocasTagDefinition( Name: "t", DeviceHostAddress: "focas://h:8193", Address: "R100", DataType: FocasDataType.Int16, Writable: false); var options = sut.Invoke([tag]); options.Tags.Count.ShouldBe(1); options.Tags[0].ShouldBeSameAs(tag); } }