public void Penalties_GetTotal()
        {
            // Arrange
            var character    = Mock.Of <ICharacter>();
            var abilityScore = Mock.Of <IAbilityScore>();

            var mockModifierTracker = new Mock <IModifierTracker>();

            mockModifierTracker.Setup(mt => mt.GetTotal())
            .Returns(1);

            var mockAttackBonus = new Mock <IUniversalAttackBonus>();

            mockAttackBonus.Setup(mab => mab.Penalties)
            .Returns(mockModifierTracker.Object);

            WeaponAttackBonus wab = new WeaponAttackBonus(character, abilityScore, mockAttackBonus.Object);

            // Act
            var result = wab.Penalties.GetTotal();

            // Assert
            Assert.AreEqual(1, result,
                            "Universal penalties to attack should be applied to weapon attack bonuses.");
        }
        public void KeyAbilityScore_NullAssignment_Throws()
        {
            // Arrange
            var character    = Mock.Of <ICharacter>();
            var abilityScore = Mock.Of <IAbilityScore>();
            var attackBonus  = Mock.Of <IUniversalAttackBonus>();

            WeaponAttackBonus wab = new WeaponAttackBonus(character, abilityScore, attackBonus);

            // Act
            TestDelegate assignment = () => wab.KeyAbilityScore = null;

            // Assert
            Assert.Throws <ArgumentNullException>(assignment,
                                                  "Assigning a null value to WeaponAttackBonus.KeyAbilityScore should throw an ArgumentNullException.");
        }
        public void KeyAbilityScore_PassThrough()
        {
            // Arrange
            var character    = Mock.Of <ICharacter>();
            var abilityScore = Mock.Of <IAbilityScore>();
            var attackBonus  = Mock.Of <IUniversalAttackBonus>();

            WeaponAttackBonus wab = new WeaponAttackBonus(character, abilityScore, attackBonus);

            // Act
            IAbilityScore keyAbilityScore = wab.KeyAbilityScore;

            // Assert
            Assert.AreSame(abilityScore, keyAbilityScore,
                           $"By default, the key ability score returned from the { nameof(WeaponAttackBonus.KeyAbilityScore) } property should be the same instance that was passed into the constructor.");
        }
        public void GetSizeModifier_Large_Neg1()
        {
            // Arrange
            var mockCharacter = new Mock <ICharacter>();

            mockCharacter.Setup(c => c.Size)
            .Returns(SizeCategory.Large);
            var abilityScore = Mock.Of <IAbilityScore>();
            var attackBonus  = Mock.Of <IUniversalAttackBonus>();

            WeaponAttackBonus wab = new WeaponAttackBonus(mockCharacter.Object, abilityScore, attackBonus);

            // Act
            var result = wab.GetSizeModifier();

            // Assert
            Assert.AreEqual(-1, result,
                            "A large character should receive a -1 penalty to attack rolls.");
        }
        public void GetSizeModifier_Medium_Zero()
        {
            // Arrange
            var mockCharacter = new Mock <ICharacter>();

            mockCharacter.Setup(c => c.Size)
            .Returns(SizeCategory.Medium);
            var abilityScore = Mock.Of <IAbilityScore>();
            var attackBonus  = Mock.Of <IUniversalAttackBonus>();

            WeaponAttackBonus wab = new WeaponAttackBonus(mockCharacter.Object, abilityScore, attackBonus);

            // Act
            var result = wab.GetSizeModifier();

            // Assert
            Assert.AreEqual(0, result,
                            "A medium character should receive a +0 bonus to attack rolls.");
        }
        public void GetTotal_Aggregates()
        {
            // Arrange
            var universalAttackBonus = Mock.Of <IUniversalAttackBonus>();

            var mockAbilityScore = new Mock <IAbilityScore>();

            mockAbilityScore.Setup(mas => mas.GetModifier())
            .Returns(2);

            var mockBaseAttackBonus = new Mock <IBaseAttackBonus>();

            mockBaseAttackBonus.Setup(mbab => mbab.GetTotal())
            .Returns(20);

            var mockAttackBonusSection = new Mock <IAttackBonusSection>();

            mockAttackBonusSection.Setup(mbabs => mbabs.BaseAttackBonus)
            .Returns(mockBaseAttackBonus.Object);

            var mockCharacter = new Mock <ICharacter>();

            mockCharacter.Setup(c => c.Size)
            .Returns(SizeCategory.Small);
            mockCharacter.Setup(c => c.AttackBonuses)
            .Returns(mockAttackBonusSection.Object);

            WeaponAttackBonus wab = new WeaponAttackBonus(mockCharacter.Object, mockAbilityScore.Object, universalAttackBonus);

            wab.EnhancementBonuses.Add(() => 3);
            wab.UntypedBonuses.Add(() => 4);
            wab.Penalties.Add(() => 5);

            // Act
            var total = wab.GetTotal();

            // Assert
            Assert.AreEqual(25, total,
                            "+25 = (20 BAB) + (1 size) + (2 ability) + (3 enhancement) + (4 untyped) - (5 penalties)");
        }