Files
PkmnLib.NET/Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/FellStingerTests.cs

116 lines
4.2 KiB
C#

using PkmnLib.Dynamic.Models;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
/// <summary>
/// Tests for the <see cref="FellStinger"/> move script.
/// Gen VII Bulbapedia behavior ("Generation VII onwards"): "It now raises the user's Attack stat by three
/// stages if it causes the targeted Pokémon to faint."
/// </summary>
public class FellStingerTests
{
/// <summary>
/// Creates a fully mocked test setup for Fell Stinger tests.
/// </summary>
private static (FellStinger script, IExecutingMove move, IBattlePokemon user, IBattlePokemon target)
CreateTestSetup(bool targetFainted)
{
var script = new FellStinger();
var move = Substitute.For<IExecutingMove>();
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
var target = Substitute.For<IBattlePokemon>();
target.IsFainted.Returns(targetFainted);
return (script, move, user, target);
}
/// <summary>
/// Helper to find the first ChangeStatBoost call received by a Pokémon substitute.
/// </summary>
private static object[]? GetStatBoostArguments(IBattlePokemon pokemon)
{
var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "ChangeStatBoost");
return call?.GetArguments()!;
}
/// <summary>
/// Bulbapedia: "It now raises the user's Attack stat by three stages if it causes the targeted Pokémon
/// to faint."
/// When the target fainted from the hit, the user's Attack stat is boosted.
/// </summary>
[Test]
public async Task OnAfterHits_TargetFainted_RaisesUserAttack()
{
// Arrange
var (script, move, user, target) = CreateTestSetup(true);
// Act
script.OnAfterHits(move, target);
// Assert
var arguments = GetStatBoostArguments(user);
await Assert.That(arguments).IsNotNull();
await Assert.That((Statistic)arguments![0]!).IsEqualTo(Statistic.Attack);
}
/// <summary>
/// Bulbapedia: "It now raises the user's Attack stat by three stages if it causes the targeted Pokémon
/// to faint."
/// In Generation VII the boost is three stages (up from two stages in Generation VI).
/// </summary>
[Test]
public async Task OnAfterHits_TargetFainted_AttackRaisedByThreeStages()
{
// Arrange
var (script, move, user, target) = CreateTestSetup(true);
// Act
script.OnAfterHits(move, target);
// Assert
var arguments = GetStatBoostArguments(user);
await Assert.That(arguments).IsNotNull();
await Assert.That((sbyte)arguments![1]!).IsEqualTo((sbyte)3);
}
/// <summary>
/// Bulbapedia: "It now raises the user's Attack stat by three stages if it causes the targeted Pokémon
/// to faint."
/// The boost is applied by the user to itself, so it must be self-inflicted and not forced.
/// </summary>
[Test]
public async Task OnAfterHits_TargetFainted_BoostIsSelfInflictedAndNotForced()
{
// Arrange
var (script, move, user, target) = CreateTestSetup(true);
// Act
script.OnAfterHits(move, target);
// Assert
var arguments = GetStatBoostArguments(user);
await Assert.That(arguments).IsNotNull();
await Assert.That((bool)arguments![2]!).IsTrue();
await Assert.That((bool)arguments[3]!).IsFalse();
}
/// <summary>
/// Bulbapedia: the Attack boost only happens "if it causes the targeted Pokémon to faint".
/// If the target survives the hit, no stat boost is applied.
/// </summary>
[Test]
public async Task OnAfterHits_TargetNotFainted_NoStatBoost()
{
// Arrange
var (script, move, user, target) = CreateTestSetup(false);
// Act
script.OnAfterHits(move, target);
// Assert - ChangeStatBoost should never be called. (Checked via ReceivedCalls, as arg matchers cannot
// be used with EventBatchId parameters: its parameterless constructor generates a random Guid.)
await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ChangeStatBoost")).IsFalse();
}
}