Files
XplorePlane/XplorePlane.Tests/ViewModels/EventLogViewModelTests.cs
T
zhengxuan.zhang 0ccf9c529e 新增调试页面
2026-05-16 13:44:36 +08:00

213 lines
6.9 KiB
C#

using Moq;
using System;
using System.Linq;
using System.Windows.Threading;
using Xunit;
using XP.Common.Logging.Interfaces;
using XplorePlane.Models;
using XplorePlane.Services.AppState;
using XplorePlane.ViewModels.Debug;
namespace XplorePlane.Tests.ViewModels
{
/// <summary>
/// EventLogViewModel 单元测试
/// Unit tests for EventLogViewModel
/// </summary>
public class EventLogViewModelTests
{
private readonly Mock<IAppStateService> _mockAppStateService;
private readonly Mock<ILoggerService> _mockLoggerService;
private readonly Dispatcher _dispatcher;
public EventLogViewModelTests()
{
_mockAppStateService = new Mock<IAppStateService>();
_mockLoggerService = new Mock<ILoggerService>();
// 创建 Dispatcher(需要在 STA 线程上)
// Create Dispatcher (needs to be on STA thread)
_dispatcher = Dispatcher.CurrentDispatcher;
// 设置 logger mock 返回自身(链式调用)
// Setup logger mock to return itself (method chaining)
_mockLoggerService.Setup(l => l.ForModule<EventLogViewModel>())
.Returns(_mockLoggerService.Object);
}
[Fact]
public void Constructor_InitializesFilterOptionsWithAllStatesEnabled()
{
// Arrange & Act
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
// Assert
Assert.Equal(8, viewModel.FilterOptions.Count);
Assert.True(viewModel.FilterOptions["MotionState"]);
Assert.True(viewModel.FilterOptions["RaySourceState"]);
Assert.True(viewModel.FilterOptions["DetectorState"]);
Assert.True(viewModel.FilterOptions["SystemState"]);
Assert.True(viewModel.FilterOptions["CameraState"]);
Assert.True(viewModel.FilterOptions["LinkedViewState"]);
Assert.True(viewModel.FilterOptions["RecipeExecutionState"]);
Assert.True(viewModel.FilterOptions["CalibrationMatrix"]);
}
[Fact]
public void ToggleFilterCommand_TogglesFilterState()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
var initialState = viewModel.FilterOptions["MotionState"];
// Act
viewModel.ToggleFilterCommand.Execute("MotionState");
// Assert
Assert.Equal(!initialState, viewModel.FilterOptions["MotionState"]);
}
[Fact]
public void SelectAllFiltersCommand_EnablesAllFilters()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
// 先禁用所有过滤器
// First disable all filters
viewModel.ClearAllFiltersCommand.Execute();
// Act
viewModel.SelectAllFiltersCommand.Execute();
// Assert
Assert.All(viewModel.FilterOptions.Values, value => Assert.True(value));
}
[Fact]
public void ClearAllFiltersCommand_DisablesAllFilters()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
// Act
viewModel.ClearAllFiltersCommand.Execute();
// Assert
Assert.All(viewModel.FilterOptions.Values, value => Assert.False(value));
}
[Fact]
public void ApplyFilter_FiltersEventLogCorrectly()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
// 添加测试数据
// Add test data
viewModel.EventLog.Add(new EventLogEntry
{
Timestamp = DateTime.Now,
EventType = "MotionStateChanged",
FieldName = "StageX",
OldValue = "0",
NewValue = "100",
Category = "MotionState"
});
viewModel.EventLog.Add(new EventLogEntry
{
Timestamp = DateTime.Now,
EventType = "RaySourceStateChanged",
FieldName = "IsOn",
OldValue = "False",
NewValue = "True",
Category = "RaySourceState"
});
// 禁用 RaySourceState 过滤器
// Disable RaySourceState filter
viewModel.FilterOptions["RaySourceState"] = false;
// Act
viewModel.ToggleFilterCommand.Execute("MotionState"); // 触发过滤器应用
viewModel.ToggleFilterCommand.Execute("MotionState"); // 恢复状态
// Assert
Assert.Single(viewModel.FilteredEventLog);
Assert.Equal("MotionState", viewModel.FilteredEventLog[0].Category);
}
[Fact]
public void EventLog_LimitsTo1000Records()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
// Act - 添加 1001 条记录
// Act - Add 1001 records
for (int i = 0; i < 1001; i++)
{
viewModel.EventLog.Add(new EventLogEntry
{
Timestamp = DateTime.Now,
EventType = "MotionStateChanged",
FieldName = "StageX",
OldValue = i.ToString(),
NewValue = (i + 1).ToString(),
Category = "MotionState"
});
}
// Assert
Assert.Equal(1000, viewModel.EventLog.Count);
}
[Fact]
public void Dispose_ClearsCollections()
{
// Arrange
var viewModel = new EventLogViewModel(
_mockAppStateService.Object,
_mockLoggerService.Object,
_dispatcher);
viewModel.EventLog.Add(new EventLogEntry
{
Timestamp = DateTime.Now,
EventType = "MotionStateChanged",
FieldName = "StageX",
OldValue = "0",
NewValue = "100",
Category = "MotionState"
});
// Act
viewModel.Dispose();
// Assert
Assert.Empty(viewModel.EventLog);
Assert.Empty(viewModel.FilteredEventLog);
}
}
}