171 lines
6.7 KiB
C#
171 lines
6.7 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.ScriptHandling;
|
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
|
using PkmnLib.Static.Species;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="HealBell"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Heal Bell cures the user, all Pokémon in the user's party, and the user's
|
|
/// allies, of all status conditions (sleep, poison, paralysis, freeze, and burn)." Since Generation VI:
|
|
/// "Heal Bell no longer affects active Pokémon with the Ability Soundproof. Inactive Pokémon are healed
|
|
/// regardless of Abilities."
|
|
/// </summary>
|
|
public class HealBellTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a mocked party member with a mocked <see cref="IBattlePokemon.Volatile"/> set, optionally
|
|
/// active on the battlefield and with a named ability.
|
|
/// </summary>
|
|
private static IBattlePokemon CreatePartyMember(bool onBattlefield = false, string? abilityName = null)
|
|
{
|
|
var pokemon = Substitute.For<IBattlePokemon>();
|
|
var volatileSet = Substitute.For<IScriptSet>();
|
|
pokemon.Volatile.Returns(volatileSet);
|
|
pokemon.IsOnBattlefield.Returns(onBattlefield);
|
|
if (abilityName != null)
|
|
{
|
|
var ability = Substitute.For<IAbility>();
|
|
ability.Name.Returns(new StringKey(abilityName));
|
|
pokemon.ActiveAbility.Returns(ability);
|
|
}
|
|
|
|
return pokemon;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup: the user plus the given other party members form a single party
|
|
/// in the battle. Returns the script, the executing move and the user (which is the move's target in
|
|
/// most tests, as Heal Bell targets the user's side).
|
|
/// </summary>
|
|
private static (HealBell script, IExecutingMove move, IBattlePokemon user) CreateTestSetup(
|
|
params IBattlePokemon?[] otherPartyMembers)
|
|
{
|
|
var script = new HealBell();
|
|
var user = CreatePartyMember(true);
|
|
|
|
var members = new List<IBattlePokemon?> { user };
|
|
members.AddRange(otherPartyMembers);
|
|
|
|
var battleParty = Substitute.For<IBattleParty>();
|
|
battleParty.BattlePokemon.Returns(members);
|
|
|
|
var battle = Substitute.For<IBattle>();
|
|
battle.Parties.Returns(new[] { battleParty });
|
|
user.Battle.Returns(battle);
|
|
|
|
var move = Substitute.For<IExecutingMove>();
|
|
move.User.Returns(user);
|
|
|
|
return (script, move, user);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper that checks whether a mocked Pokémon received a <see cref="IBattlePokemon.ClearStatus"/> call.
|
|
/// </summary>
|
|
private static bool ReceivedClearStatus(IBattlePokemon pokemon) =>
|
|
pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ClearStatus");
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Heal Bell cures the user, all Pokémon in the user's party, and the user's allies, of all
|
|
/// status conditions (sleep, poison, paralysis, freeze, and burn)." Every non-empty slot of the user's
|
|
/// party is cured, including inactive Pokémon; empty party slots are skipped without throwing.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_TargetInUsersParty_CuresStatusOfAllPartyMembers()
|
|
{
|
|
// Arrange
|
|
var inactiveMember = CreatePartyMember();
|
|
var activeMember = CreatePartyMember(true);
|
|
var (script, move, user) = CreateTestSetup(inactiveMember, activeMember, null);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedClearStatus(user)).IsTrue();
|
|
await Assert.That(ReceivedClearStatus(inactiveMember)).IsTrue();
|
|
await Assert.That(ReceivedClearStatus(activeMember)).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: Heal Bell cures "all Pokémon in the user's party". A target that is not in any party
|
|
/// (e.g. outside of the battle's known parties) results in no effect and no exception.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_TargetNotInAnyParty_DoesNothing()
|
|
{
|
|
// Arrange
|
|
var (script, move, user) = CreateTestSetup();
|
|
var strayTarget = CreatePartyMember();
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, strayTarget, 0);
|
|
|
|
// Assert - nobody is cured because no party contains the target
|
|
await Assert.That(ReceivedClearStatus(user)).IsFalse();
|
|
await Assert.That(ReceivedClearStatus(strayTarget)).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation VI, still applicable in Gen VII): "Inactive Pokémon are healed regardless of
|
|
/// Abilities." A party member with Soundproof that is not on the battlefield is still cured.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_InactiveSoundproofPartyMember_StillCured()
|
|
{
|
|
// Arrange
|
|
var soundproofMember = CreatePartyMember(false, "soundproof");
|
|
var (script, move, user) = CreateTestSetup(soundproofMember);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedClearStatus(soundproofMember)).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation VI, still applicable in Gen VII): "Heal Bell no longer affects active Pokémon
|
|
/// with the Ability Soundproof." An active party member with Soundproof is not cured.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_ActiveSoundproofPartyMember_NotCured()
|
|
{
|
|
// Arrange
|
|
var soundproofMember = CreatePartyMember(true, "soundproof");
|
|
var (script, move, user) = CreateTestSetup(soundproofMember);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedClearStatus(soundproofMember)).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: Heal Bell cures "all status conditions (sleep, poison, paralysis, freeze, and burn)".
|
|
/// Confusion is a volatile status, not a status condition, and is not cured by Heal Bell; a confused
|
|
/// party member keeps its <see cref="Confusion"/> volatile script.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_ConfusedPartyMember_ConfusionNotCured()
|
|
{
|
|
// Arrange
|
|
var confusedMember = CreatePartyMember();
|
|
var confusionKey = ScriptUtils.ResolveName<Confusion>();
|
|
confusedMember.Volatile.Contains(confusionKey).Returns(true);
|
|
var (script, move, user) = CreateTestSetup(confusedMember);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert - the confusion volatile is not removed
|
|
await Assert.That(confusedMember.Volatile.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove"))
|
|
.IsFalse();
|
|
}
|
|
} |