using PkmnLib.Dynamic.Events; using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Static; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: "Dragon Ascent inflicts damage and then lowers the user's Defense stat /// and Special Defense stat by one stage each." /// public class DragonAscentTests { private static (DragonAscent script, IExecutingMove move, IPokemon user) CreateTestSetup() { var script = new DragonAscent(); var move = Substitute.For(); var user = Substitute.For(); move.User.Returns(user); return (script, move, user); } /// /// Helper checking whether the given Pokémon received a ChangeStatBoost call for the given stat with /// a one-stage self-inflicted, non-forced drop. /// private static bool ReceivedSelfInflictedDrop(IPokemon pokemon, Statistic stat) => pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ChangeStatBoost" && (Statistic)c.GetArguments()[0]! == stat && (sbyte)c.GetArguments()[1]! == -1 && (bool)c.GetArguments()[2]! && !(bool)c.GetArguments()[3]!); /// /// Bulbapedia: "lowers the user's Defense stat [...] by one stage". The stat change is self-inflicted /// and not forced. /// [Test] public async Task OnSecondaryEffect_MoveHits_LowersUserDefenseByOneStage() { // Arrange var (script, move, user) = CreateTestSetup(); var target = Substitute.For(); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(ReceivedSelfInflictedDrop(user, Statistic.Defense)).IsTrue(); } /// /// Bulbapedia: "lowers the user's [...] Special Defense stat by one stage". The stat change is /// self-inflicted and not forced. /// [Test] public async Task OnSecondaryEffect_MoveHits_LowersUserSpecialDefenseByOneStage() { // Arrange var (script, move, user) = CreateTestSetup(); var target = Substitute.For(); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(ReceivedSelfInflictedDrop(user, Statistic.SpecialDefense)).IsTrue(); } /// /// Bulbapedia: the drop hits the user's stats, not the target's. The target's stat stages are left /// untouched. /// [Test] public async Task OnSecondaryEffect_MoveHits_DoesNotChangeTargetStats() { // Arrange var (script, move, _) = CreateTestSetup(); var target = Substitute.For(); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(target.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ChangeStatBoost")).IsFalse(); } /// /// Both stat drops are reported under the same event batch, so they display as a single combined /// event. /// [Test] public async Task OnSecondaryEffect_MoveHits_BothStatDropsShareEventBatch() { // Arrange var (script, move, user) = CreateTestSetup(); var target = Substitute.For(); // Act script.OnSecondaryEffect(move, target, 0); // Assert var batchIds = user.ReceivedCalls().Where(c => c.GetMethodInfo().Name == "ChangeStatBoost") .Select(c => (EventBatchId)c.GetArguments()[4]!).Distinct().ToList(); await Assert.That(batchIds.Count).IsEqualTo(1); } }