using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Bulbapedia: "Final Gambit causes the user to faint, and the target receives damage equal to the user's /// remaining HP before using Final Gambit." /// public class FinalGambitTests { /// /// Creates a fully mocked test setup for Final Gambit tests. /// private static (FinalGambit script, IExecutingMove move, IBattlePokemon user, IBattlePokemon target) CreateTestSetup(uint userCurrentHealth) { var script = new FinalGambit(); var move = Substitute.For(); var user = Substitute.For(); user.CurrentHealth.Returns(userCurrentHealth); move.User.Returns(user); var target = Substitute.For(); return (script, move, user, target); } /// /// Helper to extract the damage amount from the user's received Damage calls. /// private static uint? GetDamageAmount(IBattlePokemon pokemon) { var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Damage"); return call != null ? (uint)call.GetArguments()[0]! : null; } /// /// Helper to extract the damage source from the user's received Damage calls. /// private static DamageSource? GetDamageSource(IBattlePokemon pokemon) { var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Damage"); return call != null ? (DamageSource)call.GetArguments()[1]! : null; } /// /// Bulbapedia: "the target receives damage equal to the user's remaining HP before using Final Gambit." /// The move damage is replaced with the user's current HP, regardless of what the damage formula produced. /// [Test, Arguments(1u), Arguments(150u), Arguments(400u)] public async Task ChangeMoveDamage_SetsDamageToUserRemainingHp(uint userCurrentHealth) { // Arrange var (script, move, _, target) = CreateTestSetup(userCurrentHealth); uint damage = 9999; // Act script.ChangeMoveDamage(move, target, 0, ref damage); // Assert await Assert.That(damage).IsEqualTo(userCurrentHealth); } /// /// Bulbapedia: "Final Gambit causes the user to faint". /// After the move hits, the user takes at least its full remaining HP as damage, so it always faints. /// [Test] public async Task OnSecondaryEffect_MoveHits_UserTakesAtLeastItsRemainingHpAsDamage() { // Arrange const uint currentHealth = 100; var (script, move, user, target) = CreateTestSetup(currentHealth); // Act script.OnSecondaryEffect(move, target, 0); // Assert - the self-damage is at least the user's remaining HP, so the user faints var damage = GetDamageAmount(user); await Assert.That(damage).IsNotNull(); await Assert.That(damage!.Value >= currentHealth).IsTrue(); } /// /// Bulbapedia: "The move's side effect is not considered as inflicting damage to the user, and so if the /// user is holding a Focus Band, Focus Sash, or has Sturdy, they will not activate and the user will /// still faint." /// The self-inflicted faint is therefore indirect damage (), not move damage. /// [Test] public async Task OnSecondaryEffect_MoveHits_SelfFaintUsesMiscDamageSource() { // Arrange var (script, move, user, target) = CreateTestSetup(100); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(GetDamageSource(user)!.Value).IsEqualTo(DamageSource.Misc); } }