public void GetCurrentState_WithValidTransitions_ReturnsAttackState()
        {
            // Arrange
            var idleState    = new IdleState();
            var chaseState   = new ChaseState();
            var attackState  = new AttackState();
            var stateMachine = new StateMachine(3);

            stateMachine.Configure(idleState)
            .Link((int)Transition.EnemyInProximity, chaseState);

            stateMachine.Configure(chaseState)
            .Link((int)Transition.EnemyInAttackRange, attackState)
            .Link((int)Transition.EnemyOutOfRange, idleState);

            stateMachine.Configure(attackState)
            .Link((int)Transition.EnemyOutOfAttackRange, chaseState)
            .Link((int)Transition.EnemyOutOfRange, idleState);

            // Act
            stateMachine.PerformTransition((int)Transition.EnemyInProximity);
            stateMachine.PerformTransition((int)Transition.EnemyOutOfRange);
            stateMachine.PerformTransition((int)Transition.EnemyInProximity);
            stateMachine.PerformTransition((int)Transition.EnemyInAttackRange);

            // Assert
            stateMachine.CurrentState.Should().Be(attackState);
        }
        public void Configure_WithNullState_ThrowsArgumentNullException()
        {
            // Arrange
            var idleState    = new IdleState();
            var chaseState   = new ChaseState();
            var attackState  = new AttackState();
            var stateMachine = new StateMachine(3);

            // Act
            Action action = () => stateMachine.Configure(null)
                            .Link((int)Transition.EnemyInProximity, chaseState);

            // Assert
            action.Should().Throw <ArgumentNullException>();
        }
        public void Link_WithExistingTransitionInState_ThrowsException()
        {
            // Arrange
            var idleState    = new IdleState();
            var chasteState  = new ChaseState();
            var stateMachine = new StateMachine(2);

            // Act
            Action action = () => stateMachine.Configure(idleState)
                            .Link((int)Transition.EnemyInProximity, chasteState)
                            .Link((int)Transition.EnemyInProximity, chasteState);

            // Assert
            action.Should().Throw <Exception>();
        }
        public void PerformTransition_WithNonConfiguredState_ThrowsException()
        {
            // Arrange
            var idleState    = new IdleState();
            var chaseState   = new ChaseState();
            var stateMachine = new StateMachine(2);

            stateMachine.Configure(idleState)
            .Link((int)Transition.EnemyInProximity, chaseState);

            // Act
            Action action = () => stateMachine.PerformTransition((int)Transition.EnemyInProximity);

            // Assert
            action.Should().Throw <Exception>();
        }
        public void Configure_WithMoreStates_ThrowsArgumentOutOfRangeException()
        {
            // Arrange
            var idleState    = new IdleState();
            var chaseState   = new ChaseState();
            var attackState  = new AttackState();
            var stateMachine = new StateMachine(2);

            stateMachine.Configure(idleState)
            .Link((int)Transition.EnemyInProximity, chaseState);

            stateMachine.Configure(chaseState)
            .Link((int)Transition.EnemyInAttackRange, attackState)
            .Link((int)Transition.EnemyOutOfRange, idleState);

            // Act
            Action action = () => stateMachine.Configure(attackState);

            // Assert
            action.Should().Throw <ArgumentOutOfRangeException>();
        }
        public void Configure_WithAlreadyConfiguredState_ThrowsException()
        {
            // Arrange
            var idleState    = new IdleState();
            var chaseState   = new ChaseState();
            var attackState  = new AttackState();
            var stateMachine = new StateMachine(3);

            // Act
            stateMachine.Configure(idleState)
            .Link((int)Transition.EnemyInProximity, chaseState);

            stateMachine.Configure(chaseState)
            .Link((int)Transition.EnemyInAttackRange, attackState)
            .Link((int)Transition.EnemyOutOfRange, idleState);

            Action action = () => stateMachine.Configure(chaseState);

            // Assert
            action.Should().Throw <Exception>();
        }