using System.Threading.Tasks; using Xunit; using XP.Hardware.MotionControl.Abstractions.Enums; using XP.Hardware.MotionControl.Implementations; namespace XplorePlane.Tests.Hardware { public class SimulatedRotaryAxisTests { [Fact] public async Task MoveToTarget_SetsStatusToMoving_ThenIdle() { // Arrange - use fast speed for quicker test var axis = new SimulatedRotaryAxis( RotaryAxisId.DetectorSwing, minAngle: -180, maxAngle: 180, enabled: true, defaultSpeed: 200); // Act var result = axis.MoveToTarget(90); // Assert - should be Moving immediately after call Assert.True(result.Success); Assert.Equal(AxisStatus.Moving, axis.Status); // Wait for move to complete (90° at 200°/s = 450ms, add generous buffer) await Task.Delay(1000); Assert.Equal(AxisStatus.Idle, axis.Status); Assert.Equal(90.0, axis.ActualAngle, precision: 1); } [Fact] public void MoveToTarget_OutOfRange_ReturnsFail() { // Arrange var axis = new SimulatedRotaryAxis( RotaryAxisId.DetectorSwing, minAngle: -180, maxAngle: 180, enabled: true); // Act var result = axis.MoveToTarget(200); // Assert Assert.False(result.Success); Assert.NotNull(result.ErrorMessage); } [Fact] public async Task Stop_DuringMove_KeepsCurrentAngle() { // Arrange - use slow speed so we can stop mid-move var axis = new SimulatedRotaryAxis( RotaryAxisId.DetectorSwing, minAngle: -180, maxAngle: 180, enabled: true, defaultSpeed: 10); // Act - start a long move (180° at 10°/s = 18s) axis.MoveToTarget(180); await Task.Delay(200); // Let it move a bit axis.Stop(); // Assert Assert.Equal(AxisStatus.Idle, axis.Status); Assert.True(axis.ActualAngle > 0, "Angle should have moved from 0"); Assert.True(axis.ActualAngle < 180, "Angle should not have reached target"); } } }