179 lines
7.3 KiB
C#
179 lines
7.3 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.ScriptHandling;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Side;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="BrickBreak"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Brick Break removes Light Screen and Reflect", from Generation IV onward
|
|
/// "from the target's side of the field, even if the target is an ally", and from Generation V onwards
|
|
/// "Brick Break can also remove Aurora Veil."
|
|
/// </summary>
|
|
public class BrickBreakTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a mocked Pokémon whose <see cref="IPokemonBattleData.BattleSide"/> is the given side.
|
|
/// </summary>
|
|
private static IPokemon CreatePokemonOnSide(IBattleSide side)
|
|
{
|
|
var pokemon = Substitute.For<IPokemon>();
|
|
var battleData = Substitute.For<IPokemonBattleData>();
|
|
battleData.BattleSide.Returns(side);
|
|
pokemon.BattleData.Returns(battleData);
|
|
return pokemon;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup where the user targets a Pokémon on the opposing side.
|
|
/// </summary>
|
|
private static (BrickBreak script, IExecutingMove move, IPokemon user, IScriptSet userSideScripts, IScriptSet
|
|
targetSideScripts) CreateTestSetup()
|
|
{
|
|
var script = new BrickBreak();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
|
|
var userSideScripts = Substitute.For<IScriptSet>();
|
|
var userSide = Substitute.For<IBattleSide>();
|
|
userSide.VolatileScripts.Returns(userSideScripts);
|
|
var targetSideScripts = Substitute.For<IScriptSet>();
|
|
var targetSide = Substitute.For<IBattleSide>();
|
|
targetSide.VolatileScripts.Returns(targetSideScripts);
|
|
|
|
var user = CreatePokemonOnSide(userSide);
|
|
move.User.Returns(user);
|
|
var target = CreatePokemonOnSide(targetSide);
|
|
move.Targets.Returns(new IPokemon?[] { target });
|
|
|
|
return (script, move, user, userSideScripts, targetSideScripts);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation IV onward): "Brick Break now removes Light Screen and Reflect from the target's
|
|
/// side of the field, even if the target is an ally." The screen effects are removed from the target's
|
|
/// side before the move hits. The script names match <see cref="ReflectEffect"/> and
|
|
/// <see cref="LightScreenEffect"/>.
|
|
/// </summary>
|
|
[Test, Arguments("reflect"), Arguments("light_screen")]
|
|
public async Task OnBeforeMove_ScreenOnTargetSide_RemovesScreenFromTargetSide(string screenScriptName)
|
|
{
|
|
// Arrange
|
|
var (script, move, _, _, targetSideScripts) = CreateTestSetup();
|
|
|
|
// Act
|
|
script.OnBeforeMove(move);
|
|
|
|
// Assert
|
|
targetSideScripts.Received(1).Remove(new StringKey(screenScriptName));
|
|
await Assert.That(targetSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation V onwards): "Brick Break can also remove Aurora Veil."
|
|
/// The <see cref="AuroraVeilEffect"/> is removed from the target's side as well.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_AuroraVeilOnTargetSide_RemovesAuroraVeilFromTargetSide()
|
|
{
|
|
// Arrange
|
|
var (script, move, _, _, targetSideScripts) = CreateTestSetup();
|
|
|
|
// Act
|
|
script.OnBeforeMove(move);
|
|
|
|
// Assert
|
|
targetSideScripts.Received(1).Remove(new StringKey("aurora_veil"));
|
|
await Assert.That(targetSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation IV onward): "Brick Break now removes Light Screen and Reflect from the target's
|
|
/// side of the field". When the target is an opponent, screens on the user's own side stay up.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_ScreensOnUserSide_DoesNotRemoveScreensFromUserSide()
|
|
{
|
|
// Arrange
|
|
var (script, move, _, userSideScripts, _) = CreateTestSetup();
|
|
|
|
// Act
|
|
script.OnBeforeMove(move);
|
|
|
|
// Assert
|
|
await Assert.That(userSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation IV onward): "Brick Break now removes Light Screen and Reflect from the target's
|
|
/// side of the field, even if the target is an ally." An ally shares the user's side, so targeting an ally
|
|
/// removes the screens from the user's own side.
|
|
/// </summary>
|
|
[Test,
|
|
TestFailing("BrickBreak.OnBeforeMove excludes the user's own side unconditionally, so targeting an " +
|
|
"ally removes nothing (Bulbapedia: 'removes Light Screen and Reflect from the target's " +
|
|
"side of the field, even if the target is an ally')")]
|
|
public async Task OnBeforeMove_AllyTargetOnUserSide_RemovesScreensFromUserSide()
|
|
{
|
|
// Arrange
|
|
var (script, move, user, userSideScripts, _) = CreateTestSetup();
|
|
var ally = CreatePokemonOnSide(user.BattleData!.BattleSide);
|
|
move.Targets.Returns(new IPokemon?[] { ally });
|
|
|
|
// Act
|
|
script.OnBeforeMove(move);
|
|
|
|
// Assert
|
|
await Assert.That(userSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Brick Break removes Light Screen and Reflect [...], then inflicts damage."
|
|
/// When no screens are up there is nothing to remove; the move simply proceeds without error and the
|
|
/// sides remain unaffected.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_NoScreensPresent_LeavesSidesUnchanged()
|
|
{
|
|
// Arrange
|
|
var script = new BrickBreak();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
// Real, empty script sets so the removals (if any wrongly happen) would be observable as mutations.
|
|
var userSideScripts = new ScriptSet(Substitute.For<IBattleSide>());
|
|
var targetSideScripts = new ScriptSet(Substitute.For<IBattleSide>());
|
|
var userSide = Substitute.For<IBattleSide>();
|
|
userSide.VolatileScripts.Returns(userSideScripts);
|
|
var targetSide = Substitute.For<IBattleSide>();
|
|
targetSide.VolatileScripts.Returns(targetSideScripts);
|
|
var user = CreatePokemonOnSide(userSide);
|
|
move.User.Returns(user);
|
|
var target = CreatePokemonOnSide(targetSide);
|
|
move.Targets.Returns(new IPokemon?[] { target });
|
|
|
|
// Act
|
|
script.OnBeforeMove(move);
|
|
|
|
// Assert
|
|
await Assert.That(userSideScripts.Count).IsEqualTo(0);
|
|
await Assert.That(targetSideScripts.Count).IsEqualTo(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Technical test: without any targets (e.g. outside of battle) the script does nothing and does not throw.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_NoTargets_DoesNotThrow()
|
|
{
|
|
// Arrange
|
|
var script = new BrickBreak();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
var user = Substitute.For<IPokemon>();
|
|
user.BattleData.Returns((IPokemonBattleData?)null);
|
|
move.User.Returns(user);
|
|
move.Targets.Returns(Array.Empty<IPokemon?>());
|
|
|
|
// Act & Assert
|
|
await Assert.That(() => script.OnBeforeMove(move)).ThrowsNothing();
|
|
}
|
|
} |