using FluentAssertions; using Workflow.Domain.Enums; using Workflow.Domain.Exceptions; using Workflow.Domain.StateMachine; using Xunit; using TaskStatus = Workflow.Domain.Enums.TaskStatus; namespace Workflow.Tests.StateMachine; /// /// TaskStateMachine TDD 红灯阶段测试 /// 测试任务状态机的所有合法转换与非法转换 /// /// 任务状态: Pending, Approved, Rejected, Transferred, Delegated /// 操作: Approve, Reject, Transfer, Delegate, DelegateComplete, TimeoutAutoProcess /// public class TaskStateMachineTests { private readonly TaskStateMachine _machine = new(); #region Pending → Approved [Fact] public void Transition_Pending_To_Approved() { // Arrange - 正常审批通过 var currentState = TaskStatus.Pending; var operation = TaskOperation.Approve; var context = new TaskTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Approved); } #endregion #region Pending → Rejected [Fact] public void Transition_Pending_To_Rejected() { // Arrange - 正常审批驳回 var currentState = TaskStatus.Pending; var operation = TaskOperation.Reject; var context = new TaskTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Rejected); } #endregion #region Pending → Transferred [Fact] public void Transition_Pending_To_Transferred() { // Arrange - 转办:关闭原任务,为目标人创建新任务 var currentState = TaskStatus.Pending; var operation = TaskOperation.Transfer; var context = new TaskTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Transferred); } #endregion #region Pending → Delegated [Fact] public void Transition_Pending_To_Delegated() { // Arrange - 委派:临时分配给他人处理,完成后归还 var currentState = TaskStatus.Pending; var operation = TaskOperation.Delegate; var context = new TaskTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Delegated); } #endregion #region Delegated → Pending [Fact] public void Transition_Delegated_To_Pending_On_DelegateComplete() { // Arrange - 被委派人处理完毕,任务归还给委派人 var currentState = TaskStatus.Delegated; var operation = TaskOperation.DelegateComplete; var context = new TaskTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Pending); } #endregion #region Pending → Approved/Rejected (Timeout Auto Process) [Fact] public void Transition_Pending_To_Approved_On_Timeout_With_AutoApprove_Config() { // Arrange - 超时自动审批通过(配置为自动通过) var currentState = TaskStatus.Pending; var operation = TaskOperation.TimeoutAutoProcess; var context = new TaskTransitionContext { AutoApproveOnTimeout = true, }; // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Approved); } [Fact] public void Transition_Pending_To_Rejected_On_Timeout_With_AutoReject_Config() { // Arrange - 超时自动审批驳回(配置为自动驳回) var currentState = TaskStatus.Pending; var operation = TaskOperation.TimeoutAutoProcess; var context = new TaskTransitionContext { AutoApproveOnTimeout = false, }; // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TaskStatus.Rejected); } #endregion #region Illegal Transitions - Terminal States Cannot Transition [Fact] public void Transition_Approved_To_Pending_Should_Throw() { // Arrange - 已通过的任务不能回到待处理 var currentState = TaskStatus.Approved; var operation = TaskOperation.Reject; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Rejected_To_Approved_Should_Throw() { // Arrange - 已驳回的任务不能变为通过 var currentState = TaskStatus.Rejected; var operation = TaskOperation.Approve; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Transferred_To_Approved_Should_Throw() { // Arrange - 已转办的任务不能再审批 var currentState = TaskStatus.Transferred; var operation = TaskOperation.Approve; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Transferred_To_Rejected_Should_Throw() { // Arrange - 已转办的任务不能再驳回 var currentState = TaskStatus.Transferred; var operation = TaskOperation.Reject; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Approved_To_Approved_Should_Throw() { // Arrange - 已通过的任务不能再次通过 var currentState = TaskStatus.Approved; var operation = TaskOperation.Approve; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Rejected_To_Rejected_Should_Throw() { // Arrange - 已驳回的任务不能再次驳回 var currentState = TaskStatus.Rejected; var operation = TaskOperation.Reject; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion #region Illegal Transitions - DelegateComplete Only From Delegated [Fact] public void Transition_Pending_DelegateComplete_Should_Throw() { // Arrange - 非委派状态不能完成委派 var currentState = TaskStatus.Pending; var operation = TaskOperation.DelegateComplete; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Approved_DelegateComplete_Should_Throw() { // Arrange - 已通过的任务不能完成委派 var currentState = TaskStatus.Approved; var operation = TaskOperation.DelegateComplete; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion #region Illegal Transitions - Timeout Only From Pending [Fact] public void Transition_Delegated_TimeoutAutoProcess_Should_Throw() { // Arrange - 委派状态不支持超时自动处理 var currentState = TaskStatus.Delegated; var operation = TaskOperation.TimeoutAutoProcess; var context = new TaskTransitionContext { AutoApproveOnTimeout = true, }; // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Approved_TimeoutAutoProcess_Should_Throw() { // Arrange - 已通过的任务不支持超时处理 var currentState = TaskStatus.Approved; var operation = TaskOperation.TimeoutAutoProcess; var context = new TaskTransitionContext { AutoApproveOnTimeout = true, }; // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion #region Illegal Transitions - Delegated State Restrictions [Fact] public void Transition_Delegated_To_Approved_Should_Throw() { // Arrange - 委派中的任务不能直接审批通过,需先归还 var currentState = TaskStatus.Delegated; var operation = TaskOperation.Approve; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Delegated_To_Rejected_Should_Throw() { // Arrange - 委派中的任务不能直接驳回,需先归还 var currentState = TaskStatus.Delegated; var operation = TaskOperation.Reject; var context = new TaskTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion }