This commit is contained in:
193
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/HealBellTests.cs
Normal file
193
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/HealBellTests.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
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="IPokemon.Volatile"/> set and
|
||||
/// <see cref="IPokemon.BattleData"/>, optionally active on the battlefield and with a named ability.
|
||||
/// </summary>
|
||||
private static IPokemon CreatePartyMember(bool onBattlefield = false, string? abilityName = null)
|
||||
{
|
||||
var pokemon = Substitute.For<IPokemon>();
|
||||
var volatileSet = Substitute.For<IScriptSet>();
|
||||
pokemon.Volatile.Returns(volatileSet);
|
||||
var battleData = Substitute.For<IPokemonBattleData>();
|
||||
battleData.IsOnBattlefield.Returns(onBattlefield);
|
||||
pokemon.BattleData.Returns(battleData);
|
||||
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, IPokemon user) CreateTestSetup(
|
||||
params IPokemon?[] otherPartyMembers)
|
||||
{
|
||||
var script = new HealBell();
|
||||
var user = CreatePartyMember(true);
|
||||
|
||||
var members = new List<IPokemon?> { user };
|
||||
members.AddRange(otherPartyMembers);
|
||||
|
||||
var party = Substitute.For<IPokemonParty>();
|
||||
party.GetEnumerator().Returns(_ => members.GetEnumerator());
|
||||
var battleParty = Substitute.For<IBattleParty>();
|
||||
battleParty.Party.Returns(party);
|
||||
|
||||
var battle = Substitute.For<IBattle>();
|
||||
battle.Parties.Returns(new[] { battleParty });
|
||||
user.BattleData!.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="IPokemon.ClearStatus"/> call.
|
||||
/// </summary>
|
||||
private static bool ReceivedClearStatus(IPokemon 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>
|
||||
/// Technical test: outside of battle the user has no <see cref="IPokemon.BattleData"/>; the script
|
||||
/// does nothing and does not throw.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_UserHasNoBattleData_DoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user) = CreateTestSetup();
|
||||
user.BattleData.Returns((IPokemonBattleData?)null);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, user, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(ReceivedClearStatus(user)).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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user