using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Pickers;
///
/// Gitea #540. The previous edition of this file asserted
/// Build("axis", 5) == "axis:5" for four "parameter groups" that are not FOCAS
/// addressing spaces — it pinned the exact string the driver could not parse, which is why
/// a fully-green suite coexisted with a picker whose default value was unusable. Every case
/// here therefore asserts the address ROUND-TRIPS through the driver's parser, not merely
/// that it has the expected shape.
///
public sealed class FocasAddressBuilderTests
{
[Theory]
[InlineData(FocasManualAddressKind.Pmc, "R", 100, null, "R100")]
[InlineData(FocasManualAddressKind.Pmc, "X", 0, 0, "X0.0")]
[InlineData(FocasManualAddressKind.Pmc, "F", 20, 3, "F20.3")]
[InlineData(FocasManualAddressKind.Pmc, "r", 100, null, "R100")] // letter is normalised
[InlineData(FocasManualAddressKind.Parameter, null, 1020, null, "PARAM:1020")]
[InlineData(FocasManualAddressKind.Parameter, null, 1815, 0, "PARAM:1815/0")]
[InlineData(FocasManualAddressKind.Macro, null, 500, null, "MACRO:500")]
[InlineData(FocasManualAddressKind.Macro, null, 500, 3, "MACRO:500")] // macros have no bit form
public void Build_produces_an_address_the_driver_can_parse(
FocasManualAddressKind kind, string? letter, int number, int? bit, string expected)
{
var built = FocasAddressBuilder.Build(kind, letter, number, bit);
built.ShouldBe(expected);
FocasAddress.TryParse(built).ShouldNotBeNull();
}
[Theory]
[InlineData(FocasManualAddressKind.Pmc, "Z", 10, null)] // not a PMC area letter
[InlineData(FocasManualAddressKind.Pmc, "", 10, null)] // no area chosen
[InlineData(FocasManualAddressKind.Pmc, "R", 10, 8)] // PMC bits are 0-7
[InlineData(FocasManualAddressKind.Pmc, "R", -1, null)] // negative byte
[InlineData(FocasManualAddressKind.Parameter, null, 1815, 32)] // parameter bits are 0-31
[InlineData(FocasManualAddressKind.Parameter, null, -5, null)]
public void Build_returns_empty_rather_than_an_unusable_address(
FocasManualAddressKind kind, string? letter, int number, int? bit)
=> FocasAddressBuilder.Build(kind, letter, number, bit).ShouldBeEmpty();
///
/// The contract that matters, stated over the whole offered surface rather than a sample:
/// nothing the picker can compose is unreadable. Every PMC area the picker lists, at a
/// whole-word address and at each legal bit.
///
[Fact]
public void Every_offered_pmc_area_composes_a_parseable_address()
{
foreach (var letter in FocasAddressBuilder.PmcLetters)
{
foreach (int? bit in new int?[] { null, 0, 7 })
{
var built = FocasAddressBuilder.Build(FocasManualAddressKind.Pmc, letter, 12, bit);
built.ShouldNotBeEmpty($"PMC area '{letter}' bit '{bit}' composed nothing");
FocasAddress.TryParse(built).ShouldNotBeNull($"'{built}' does not parse");
}
}
}
}