using System;
using System.Windows;
using Moq;
using Serilog;
using Xunit;
using XP.Hardware.RaySource.Services;
using XplorePlane.Models;
using XplorePlane.Services.AppState;
namespace XplorePlane.Tests.Services
{
///
/// AppStateService 单元测试。
/// 验证默认状态值、Dispose 后行为、null 参数校验、CalibrationMatrix 缺失时的错误处理。
///
public class AppStateServiceTests : IDisposable
{
private readonly AppStateService _service;
private readonly Mock _mockRaySource;
private readonly Mock _mockLogger;
public AppStateServiceTests()
{
// Ensure WPF Application exists for Dispatcher
if (Application.Current == null)
{
new Application();
}
_mockRaySource = new Mock();
_mockLogger = new Mock();
_service = new AppStateService(_mockRaySource.Object, _mockLogger.Object);
}
public void Dispose()
{
_service.Dispose();
}
// ── 默认状态值验证 ──
[Fact]
public void DefaultState_MotionState_IsDefault()
{
Assert.Same(MotionState.Default, _service.MotionState);
}
[Fact]
public void DefaultState_RaySourceState_IsDefault()
{
Assert.Same(RaySourceState.Default, _service.RaySourceState);
}
[Fact]
public void DefaultState_SystemState_IsDefault()
{
Assert.Same(SystemState.Default, _service.SystemState);
}
[Fact]
public void DefaultState_CalibrationMatrix_IsNull()
{
Assert.Null(_service.CalibrationMatrix);
}
// ── null 参数抛出 ArgumentNullException ──
[Fact]
public void UpdateMotionState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws(() => _service.UpdateMotionState(null!));
}
[Fact]
public void UpdateRaySourceState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws(() => _service.UpdateRaySourceState(null!));
}
[Fact]
public void UpdateDetectorState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws(() => _service.UpdateDetectorState(null!));
}
[Fact]
public void UpdateSystemState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws(() => _service.UpdateSystemState(null!));
}
// ── Dispose 后 Update 被忽略 ──
[Fact]
public void Dispose_ThenUpdate_IsIgnored()
{
var originalState = _service.MotionState;
_service.Dispose();
// Should not throw, and state should remain unchanged
var newState = new MotionState(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
_service.UpdateMotionState(newState);
Assert.Same(originalState, _service.MotionState);
}
// ── CalibrationMatrix 为 null 时 RequestLinkedView 设置错误状态 ──
[Fact]
public void RequestLinkedView_NoCalibrationMatrix_SetsErrorState()
{
// CalibrationMatrix is null by default
Assert.Null(_service.CalibrationMatrix);
_service.RequestLinkedView(100.0, 200.0);
Assert.True(_service.SystemState.HasError);
Assert.NotEmpty(_service.SystemState.ErrorMessage);
}
}
}