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, IPokemon user, IPokemon 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(IPokemon 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(IPokemon 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);
}
}