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

164 lines
6.8 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.Side;
using PkmnLib.Static;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
/// <summary>
/// Tests for the <see cref="Defog"/> move script.
/// Gen VII Bulbapedia behavior: "Defog lowers the target's evasion by one stage" and clears field effects:
/// "It removes Spikes, Toxic Spikes, Stealth Rock, and Sticky Web from both sides, while Light Screen,
/// Reflect, Safeguard, Mist, and Aurora Veil are cleared from the target's side only."
/// </summary>
public class DefogTests
{
/// <summary>
/// Creates a fully mocked test setup where the target is on side 1 and the user on side 0.
/// </summary>
private static (Defog script, IExecutingMove move, IPokemon target, IScriptSet targetSideScripts, IScriptSet
userSideScripts) CreateTestSetup()
{
var script = new Defog();
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 battle = Substitute.For<IBattle>();
battle.Sides.Returns(new[] { userSide, targetSide });
var user = Substitute.For<IPokemon>();
var userBattleData = Substitute.For<IPokemonBattleData>();
userBattleData.Battle.Returns(battle);
userBattleData.SideIndex.Returns((byte)0);
user.BattleData.Returns(userBattleData);
move.User.Returns(user);
var target = Substitute.For<IPokemon>();
var targetBattleData = Substitute.For<IPokemonBattleData>();
targetBattleData.Battle.Returns(battle);
targetBattleData.SideIndex.Returns((byte)1);
target.BattleData.Returns(targetBattleData);
return (script, move, target, targetSideScripts, userSideScripts);
}
/// <summary>
/// Bulbapedia: "Light Screen, Reflect, Safeguard, Mist, and Aurora Veil are cleared from the target's
/// side only." The screen and protection effects (<see cref="LightScreenEffect"/>,
/// <see cref="ReflectEffect"/>, <see cref="SafeguardEffect"/>, <see cref="MistEffect"/>) are removed
/// from the target's side.
/// </summary>
[Test, Arguments("light_screen"), Arguments("reflect"), Arguments("safe_guard"), Arguments("mist")]
public async Task OnSecondaryEffect_ScreenOnTargetSide_RemovesEffectFromTargetSide(string scriptName)
{
// Arrange
var (script, move, target, targetSideScripts, _) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
targetSideScripts.Received(1).Remove(new StringKey(scriptName));
await Assert.That(targetSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
}
/// <summary>
/// Bulbapedia: "It removes Spikes, Toxic Spikes, Stealth Rock, and Sticky Web" — the entry hazards
/// (<see cref="SpikesEffect"/>, <see cref="ToxicSpikesEffect"/>, <see cref="StealthRockEffect"/>,
/// <see cref="StickyWebEffect"/>) are removed from the target's side.
/// </summary>
[Test, Arguments("spikes"), Arguments("toxic_spikes"), Arguments("stealth_rock"), Arguments("sticky_web")]
public async Task OnSecondaryEffect_HazardOnTargetSide_RemovesHazardFromTargetSide(string scriptName)
{
// Arrange
var (script, move, target, targetSideScripts, _) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
targetSideScripts.Received(1).Remove(new StringKey(scriptName));
await Assert.That(targetSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
}
/// <summary>
/// Bulbapedia (Generations VI and VII): "It removes Spikes, Toxic Spikes, Stealth Rock, and Sticky Web
/// from both sides" — the entry hazards must also be removed from the user's own side.
/// </summary>
[Test, Arguments("spikes"), Arguments("toxic_spikes"), Arguments("stealth_rock"), Arguments("sticky_web")]
public async Task OnSecondaryEffect_HazardOnUserSide_RemovesHazardFromUserSide(string scriptName)
{
// Arrange
var (script, move, target, _, userSideScripts) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
userSideScripts.Received(1).Remove(new StringKey(scriptName));
await Assert.That(userSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
}
/// <summary>
/// Bulbapedia (Generations VI and VII): "Light Screen, Reflect, Safeguard, Mist, and Aurora Veil are
/// cleared from the target's side only." The <see cref="AuroraVeilEffect"/> must be removed as well.
/// </summary>
[Test]
public async Task OnSecondaryEffect_AuroraVeilOnTargetSide_RemovesAuroraVeilFromTargetSide()
{
// Arrange
var (script, move, target, targetSideScripts, _) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
targetSideScripts.Received(1).Remove(new StringKey("aurora_veil"));
await Assert.That(targetSideScripts.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Remove")).IsTrue();
}
/// <summary>
/// Bulbapedia: "Defog lowers the target's evasion by one stage". Neither the script nor the move data
/// applies the evasion drop, so the target's evasion is never lowered.
/// </summary>
[Test]
public async Task OnSecondaryEffect_Always_LowersTargetEvasionByOneStage()
{
// Arrange
var (script, move, target, _, _) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
await Assert.That(target.ReceivedCalls().Any(c =>
c.GetMethodInfo().Name == "ChangeStatBoost" && (Statistic)c.GetArguments()[0]! == Statistic.Evasion &&
(sbyte)c.GetArguments()[1]! == -1)).IsTrue();
}
/// <summary>
/// Technical test: without battle data (outside of battle) the secondary effect does nothing and does
/// not throw.
/// </summary>
[Test]
public async Task OnSecondaryEffect_TargetHasNoBattleData_DoesNotThrow()
{
// Arrange
var script = new Defog();
var move = Substitute.For<IExecutingMove>();
var target = Substitute.For<IPokemon>();
target.BattleData.Returns((IPokemonBattleData?)null);
// Act & Assert
await Assert.That(() => script.OnSecondaryEffect(move, target, 0)).ThrowsNothing();
}
}