public void AddSuperState_throws_ArgumentOutOfRangeException_if_substate_is_already_superstate()
        {
            var stateMachine    = new StateMachineAsync <Sale, SaleState, SaleEvent>(sale => sale.State, (sale, newState) => sale.State = newState);
            var sut             = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.ChangeDue, stateMachine);
            var openStateConfig = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.Open, stateMachine);

            //First time works fine
            openStateConfig.AddSuperstate(sut);

            //Second time blows up
            Assert.Throws <ArgumentOutOfRangeException>(() => openStateConfig.AddSuperstate(sut));
        }
        public async Task FireTriggerAsync_executes_superState_if_currentState_not_successful()
        {
            var sale = new Sale(saleID: 96)
            {
                State = SaleState.ChangeDue
            };
            var stateMachine             = new StateMachineAsync <Sale, SaleState, SaleEvent>(sale1 => sale1.State, (sale1, newState) => sale1.State = newState);
            var openState                = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.Open, stateMachine);
            var changeDueState           = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.ChangeDue, stateMachine);
            var openStatePayTriggerFired = false;

            openState
            .AddTriggerAction(SaleEvent.Pay, (sale1, _) => { openStatePayTriggerFired = true; return(Task.CompletedTask); })
            .AddTransition(SaleEvent.Pay, SaleState.Complete, name: "openStatePay");
            changeDueState.AddSuperstate(openState);
            var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale);

            var result = await changeDueState.FireTriggerAsync(parameters);

            Assert.True(openStatePayTriggerFired);
            Assert.True(result.WasTransitioned);
            Assert.Equal(SaleState.Complete, sale.State);
            Assert.Equal(SaleState.Complete, result.CurrentState);
            Assert.Equal(SaleState.ChangeDue, result.PreviousState);
            Assert.Equal(SaleState.ChangeDue, result.StartingState);
            Assert.Equal("openStatePay", result.LastTransitionName);
        }
        public async Task ExecuteReentryActionAsync_executes_ReentryAction()
        {
            var sale = new Sale(saleID: 96)
            {
                State = SaleState.Open
            };
            var transitionResult = new StateTransitionResult <SaleState, SaleEvent>(SaleEvent.AddItem
                                                                                    , SaleState.Open
                                                                                    , SaleState.Open
                                                                                    , SaleState.Open
                                                                                    , "lastTransitionName");
            var stateMachine   = new StateMachineAsync <Sale, SaleState, SaleEvent>(sale1 => sale1.State, (sale1, newState) => sale1.State = newState);
            var openState      = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.Open, stateMachine);
            var changeDueState = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.ChangeDue, stateMachine);

            changeDueState.AddSuperstate(openState);
            var changeDueEntryActionFromOpenFired = false;

            changeDueState.AddReentryAction((sale1, _) => { changeDueEntryActionFromOpenFired = true; return(Task.CompletedTask); });
            var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale);

            await changeDueState.ExecuteReentryActionAsync(parameters, transitionResult);

            Assert.True(changeDueEntryActionFromOpenFired);
        }
        public void AddSuperState_throws_ArgumentOutOfRangeException_if_configuredState_already_superState()
        {
            var stateMachine    = new StateMachineAsync <Sale, SaleState, SaleEvent>(sale => sale.State, (sale, newState) => sale.State = newState);
            var changeDueConfig = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.ChangeDue, stateMachine);
            var openStateConfig = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.Open, stateMachine);

            changeDueConfig.AddSuperstate(openStateConfig);

            Assert.Throws <ArgumentOutOfRangeException>(() => openStateConfig.AddSuperstate(changeDueConfig));
        }
        public void IsSubstateOf_returns_True_if_in_given_state_is_subState()
        {
            var stateMachine   = new StateMachineAsync <Sale, SaleState, SaleEvent>(sale1 => sale1.State, (sale1, newState) => sale1.State = newState);
            var openState      = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.Open, stateMachine);
            var changeDueState = new StateConfigurationAsync <Sale, SaleState, SaleEvent>(SaleState.ChangeDue, stateMachine);

            changeDueState.AddSuperstate(openState);

            Assert.True(changeDueState.IsSubstateOf(SaleState.Open));
            Assert.False(openState.IsSubstateOf(SaleState.ChangeDue));
        }