Files
XplorePlane/XplorePlane.Tests/ViewModels/MatrixEditorViewModelTests.cs
T
2026-08-10 14:13:32 +08:00

167 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using Prism.Events;
using XP.Common.Logging.Interfaces;
using XP.Hardware.MotionControl.Abstractions;
using XP.Hardware.MotionControl.Abstractions.Enums;
using Xunit;
using XplorePlane.Models;
using XplorePlane.Services.Cnc;
using XplorePlane.Services.Cnc.Matrix;
using XplorePlane.Views.Dialogs;
using XplorePlane.ViewModels.Cnc;
namespace XplorePlane.Tests.ViewModels
{
public class MatrixEditorViewModelTests
{
[Fact]
public void Constructor_CreatesTwoByTwoLayoutByDefault()
{
var fixture = CreateFixture();
Assert.Equal(2, fixture.ViewModel.Rows);
Assert.Equal(2, fixture.ViewModel.Columns);
Assert.Equal(4, fixture.ViewModel.Cells.Count);
Assert.Equal(new[] { 1, 4 }, fixture.ViewModel.TeachPoints.Select(point => point.Position));
}
[Fact]
public void RecordCurrentPosition_RefreshesMotionAxesAndRecordsLatestCoordinates()
{
var fixture = CreateFixture(stageXmm: 12.3456, stageYmm: -3.2546);
var teachPoint = fixture.ViewModel.CurrentTeachPoint;
fixture.ViewModel.RecordCurrentPositionCommand.Execute();
fixture.StageX.Verify(axis => axis.UpdateStatus(), Times.Once);
fixture.StageY.Verify(axis => axis.UpdateStatus(), Times.Once);
Assert.True(teachPoint.HasRecorded);
Assert.Equal(12.346, teachPoint.RecordedX);
Assert.Equal(-3.255, teachPoint.RecordedY);
Assert.Equal("X:12.346 Y:-3.255 mm", teachPoint.CoordinateLabel);
}
[Fact]
public void AutoGenerate_UsesRecordedMillimeterCoordinatesWithoutUnitScaling()
{
var fixture = CreateFixture(stageXmm: 10.1234, stageYmm: 20.1234);
fixture.ViewModel.RecordCurrentPositionCommand.Execute();
fixture.StageX.SetupGet(axis => axis.ActualPosition).Returns(11.2345);
fixture.StageY.SetupGet(axis => axis.ActualPosition).Returns(25.6789);
fixture.ViewModel.RecordCurrentPositionCommand.Execute();
fixture.ViewModel.AutoGenerateCommand.Execute();
var topRight = fixture.ViewModel.Cells[1];
var bottomLeft = fixture.ViewModel.Cells[2];
var bottomRight = fixture.ViewModel.Cells[3];
Assert.Equal(1.112, topRight.OffsetX);
Assert.Equal(0, topRight.OffsetY);
Assert.Equal(0, bottomLeft.OffsetX);
Assert.Equal(5.556, bottomLeft.OffsetY);
Assert.Equal(1.112, bottomRight.OffsetX);
Assert.Equal(5.556, bottomRight.OffsetY);
Assert.Equal("X:10.123 Y:25.679", bottomLeft.CoordinateLabel);
Assert.Equal("X:11.235 Y:25.679", bottomRight.CoordinateLabel);
}
[Fact]
public void CellCommands_RecordAdditionalPositionAndToggleEnabledState()
{
var fixture = CreateFixture(stageXmm: 7.1234, stageYmm: 8.5678);
var targetCell = fixture.ViewModel.Cells[1];
fixture.ViewModel.RecordCellPositionCommand.Execute(targetCell);
var additionalPoint = Assert.Single(
fixture.ViewModel.TeachPoints,
point => point.Position == 2);
Assert.True(additionalPoint.IsTaught);
Assert.Equal(7.123, additionalPoint.RecordedX);
Assert.Equal(8.568, additionalPoint.RecordedY);
Assert.Equal(MatrixCellTeachState.Taught, fixture.ViewModel.Cells[1].TeachState);
fixture.ViewModel.ToggleCellCommand.Execute(fixture.ViewModel.Cells[1]);
Assert.False(fixture.ViewModel.Cells[1].IsEnabled);
}
private static Fixture CreateFixture(double stageXmm = 0, double stageYmm = 0)
{
var matrixService = new Mock<IMatrixService>();
matrixService
.Setup(service => service.CreateLayout(
It.IsAny<int>(), It.IsAny<int>(), It.IsAny<double>(), It.IsAny<double>()))
.Returns<int, int, double, double>(CreateLayout);
matrixService
.Setup(service => service.ToggleCellEnabled(
It.IsAny<MatrixLayout>(), It.IsAny<int>(), It.IsAny<int>()))
.Returns<MatrixLayout, int, int>((layout, row, column) =>
{
var cells = layout.Cells
.Select(cell => cell.Row == row && cell.Column == column
? cell with { IsEnabled = !cell.IsEnabled }
: cell)
.ToList()
.AsReadOnly();
return layout with { Cells = cells };
});
var stageX = new Mock<ILinearAxis>();
stageX.SetupGet(axis => axis.ActualPosition).Returns(stageXmm);
var stageY = new Mock<ILinearAxis>();
stageY.SetupGet(axis => axis.ActualPosition).Returns(stageYmm);
var motionSystem = new Mock<IMotionSystem>();
motionSystem.Setup(system => system.GetLinearAxis(AxisId.StageX)).Returns(stageX.Object);
motionSystem.Setup(system => system.GetLinearAxis(AxisId.StageY)).Returns(stageY.Object);
var logger = new Mock<ILoggerService>();
logger.Setup(service => service.ForModule<MatrixEditorViewModel>()).Returns(logger.Object);
var viewModel = new MatrixEditorViewModel(
matrixService.Object,
Mock.Of<ICncProgramService>(),
Mock.Of<IMatrixExecutionCoordinator>(),
motionSystem.Object,
Mock.Of<IEventAggregator>(),
logger.Object,
Mock.Of<IApplicationDialogService>());
return new Fixture(viewModel, stageX, stageY);
}
private static MatrixLayout CreateLayout(int rows, int columns, double rowSpacing, double columnSpacing)
{
var cells = new List<MatrixCell>();
for (var row = 0; row < rows; row++)
{
for (var column = 0; column < columns; column++)
{
cells.Add(new MatrixCell(
row,
column,
column * columnSpacing,
row * rowSpacing,
true,
MatrixCellStatus.NotExecuted,
null));
}
}
return new MatrixLayout(
Guid.NewGuid(), rows, columns, rowSpacing, columnSpacing,
0, 0, string.Empty, cells.AsReadOnly());
}
private sealed record Fixture(
MatrixEditorViewModel ViewModel,
Mock<ILinearAxis> StageX,
Mock<ILinearAxis> StageY);
}
}