public void ExecuteAutoTransition_executes_AutoTransition_for_superState() { //Scenario: Sale has been paid for and goes to ChangeDue. If no change due, it should automatically transition to Complete. //ChangeDue is a substate of Open and Open has the autoForward defined for Pay. var sale = new Sale(saleID: 96) { State = SaleState.ChangeDue }; var transitionResult = new StateTransitionResult <SaleState, SaleEvent>(SaleEvent.AddItem , SaleState.Open , SaleState.Open , SaleState.ChangeDue , "lastTransitionName"); var stateMachine = new StateMachine <Sale, SaleState, SaleEvent>(sale1 => sale1.State, (sale1, newState) => sale1.State = newState); IStateConfigurationInternal <Sale, SaleState, SaleEvent> openState = stateMachine.ConfigureState(SaleState.Open) as IStateConfigurationInternal <Sale, SaleState, SaleEvent>; IStateConfigurationInternal <Sale, SaleState, SaleEvent> changeDueState = stateMachine.ConfigureState(SaleState.ChangeDue) as IStateConfigurationInternal <Sale, SaleState, SaleEvent>; changeDueState?.AddSuperstate(openState); openState?.AddAutoForwardTransition(SaleEvent.Pay, SaleState.Complete, sale1 => true /* condition indicates no change due */); var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale); var autoTransitionResult = changeDueState?.ExecuteAutoTransition(parameters, transitionResult); Assert.True(autoTransitionResult?.WasTransitioned); Assert.Equal(SaleState.Complete, sale.State); Assert.Equal(SaleState.Complete, autoTransitionResult?.CurrentState); Assert.Equal(SaleState.ChangeDue, autoTransitionResult?.PreviousState); Assert.Equal(SaleState.Open, autoTransitionResult?.StartingState); }
public async Task ExecuteAutoTransitionAsync_executes_AutoTransition_for_superState() { var sale = new Sale(saleId: 96) { State = SaleState.ChangeDue }; var transitionResult = new StateTransitionResult <SaleState, SaleEvent>(SaleEvent.Pay , SaleState.Open , SaleState.Open , SaleState.ChangeDue , "lastTransitionName"); var stateMachine = new StateMachine <Sale, SaleState, SaleEvent>(sale1 => sale1.State, (sale1, newState) => sale1.State = newState); IStateConfigurationInternal <Sale, SaleState, SaleEvent> openState = stateMachine.ConfigureState(SaleState.Open) as IStateConfigurationInternal <Sale, SaleState, SaleEvent>; IStateConfigurationInternal <Sale, SaleState, SaleEvent> changeDueState = stateMachine.ConfigureState(SaleState.ChangeDue) as IStateConfigurationInternal <Sale, SaleState, SaleEvent>; Debug.Assert(changeDueState != null, nameof(changeDueState) + " != null"); changeDueState.AddSuperstate(openState); Debug.Assert(openState != null, nameof(openState) + " != null"); openState.AddAutoForwardTransition(SaleEvent.ChangeGiven, SaleState.Complete, (sale1, _) => Task.FromResult(result: true)); var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.ChangeGiven, sale); var autoTransitionResult = await changeDueState.ExecuteAutoTransitionAsync(parameters, transitionResult); Assert.True(autoTransitionResult.WasTransitioned); Assert.Equal(SaleState.Complete, sale.State); Assert.Equal(SaleState.Complete, autoTransitionResult.CurrentState); Assert.Equal(SaleState.ChangeDue, autoTransitionResult.PreviousState); Assert.Equal(SaleState.Open, autoTransitionResult.StartingState); }
/// <summary> /// Adds this state as a substate to the given superState. /// </summary> /// <param name="superStateConfiguration">The superState.</param> public void AddSuperstate(IStateConfigurationInternal <T, TState, TTrigger> superStateConfiguration) { if (IsSubstateOf(superStateConfiguration.State)) { throw new ArgumentOutOfRangeException($"{State} is already a substate of {superStateConfiguration.State}."); } if (superStateConfiguration.IsSubstateOf(State)) { throw new InvalidOperationException($"{superStateConfiguration.State} is already a substate of {State}."); } _superstateConfig = superStateConfiguration; }