using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS;
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
///
/// Phase 4 data-type tier — axis-position scaling, config-supplied fallback path. A real
/// CNC's cnc_rddynamic2 position block carries its own base^exponent scale
/// (covered by ); a scale-less position — the
/// raw integers these tests seed — is divided by 10^PositionDecimalPlaces at the
/// publish seam.
///
[Trait("Category", "Unit")]
public sealed class FocasPositionScalingTests
{
private const string Host = "focas://10.0.0.5:8193";
// A single-axis CNC (X only) so the snapshot we seed is unambiguous.
private static FakeFocasClient SingleAxisClient(FocasDynamicSnapshot snap)
{
var c = new FakeFocasClient();
c.AxisNames.Clear();
c.AxisNames.Add(new("X", ""));
c.DynamicByAxis[1] = snap; // FOCAS axis indexing is 1-based
return c;
}
private static FocasDriver NewDriver(int positionDecimalPlaces, FakeFocasClientFactory factory)
{
return new FocasDriver(new FocasDriverOptions
{
Devices = [new FocasDeviceOptions(Host, PositionDecimalPlaces: positionDecimalPlaces)],
Probe = new FocasProbeOptions { Enabled = false },
FixedTree = new FocasFixedTreeOptions
{
Enabled = true,
PollInterval = TimeSpan.FromMilliseconds(10),
},
}, "drv-1", factory);
}
// Drive the fixed-tree poll loop and wait (bounded) for the cached value to appear.
private static async Task