This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="MiracleEye"/> move script.
|
||||
/// Behavior is verified against the Bulbapedia page for Miracle Eye (Generation VII behavior: the
|
||||
/// Generation IV base effect with the Generation V-to-VII changes applied).
|
||||
/// The lasting part of the effect (removing the Dark type's immunity to Psychic moves and ignoring
|
||||
/// evasion raises) is implemented by the <see cref="MiracleEyeEffect"/> volatile script, which the
|
||||
/// move script is responsible for attaching to the target.
|
||||
/// </summary>
|
||||
public class MiracleEyeTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a fully mocked test setup for Miracle Eye tests, with the target at the given evasion
|
||||
/// stat stage.
|
||||
/// </summary>
|
||||
private static (MiracleEye script, IExecutingMove move, IPokemon target, IScriptSet volatileSet, IHitData hitData)
|
||||
CreateTestSetup(sbyte evasionStage = 0)
|
||||
{
|
||||
var script = new MiracleEye();
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
var hitData = Substitute.For<IHitData>();
|
||||
move.GetHitData(target, 0).Returns(hitData);
|
||||
|
||||
var volatileSet = Substitute.For<IScriptSet>();
|
||||
target.Volatile.Returns(volatileSet);
|
||||
target.StatBoost.Returns(new StatBoostStatisticSet
|
||||
{
|
||||
Evasion = evasionStage,
|
||||
});
|
||||
|
||||
return (script, move, target, volatileSet, hitData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to extract all stat boost changes requested on the target through
|
||||
/// <see cref="IPokemon.ChangeStatBoost"/>.
|
||||
/// </summary>
|
||||
private static IReadOnlyList<(Statistic stat, sbyte amount)> GetStatBoostChanges(IPokemon target) =>
|
||||
target.ReceivedCalls().Where(c => c.GetMethodInfo().Name == "ChangeStatBoost")
|
||||
.Select(c => ((Statistic)c.GetArguments()[0]!, (sbyte)c.GetArguments()[1]!)).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If Miracle Eye's target is a Dark-type Pokémon, it also removes the target's
|
||||
/// immunity to Psychic-type moves. Miracle Eye's effect ends when the target switches out."
|
||||
/// The lasting effect is implemented by attaching a <see cref="MiracleEyeEffect"/> volatile script
|
||||
/// to the target.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_Always_AddsMiracleEyeEffectToTargetVolatile()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, target, volatileSet, _) = CreateTestSetup();
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var addCall = volatileSet.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Add");
|
||||
await Assert.That(addCall).IsNotNull();
|
||||
await Assert.That(addCall!.GetArguments()[0] is MiracleEyeEffect).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Miracle Eye causes accuracy checks against the target to ignore changes to the
|
||||
/// target's evasion stat stages if its evasion stat stage is greater than 0."
|
||||
/// The engine models this by resetting a raised evasion stat stage back to zero (and preventing
|
||||
/// further raises through <see cref="MiracleEyeEffect"/>).
|
||||
/// </summary>
|
||||
[Test, Arguments((sbyte)1, (sbyte)-1), Arguments((sbyte)3, (sbyte)-3), Arguments((sbyte)6, (sbyte)-6)]
|
||||
public async Task OnSecondaryEffect_PositiveEvasionStage_EvasionStageResetToZero(sbyte evasionStage,
|
||||
sbyte expectedChange)
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, target, _, _) = CreateTestSetup(evasionStage);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var changes = GetStatBoostChanges(target);
|
||||
await Assert.That(changes.Count).IsEqualTo(1);
|
||||
await Assert.That(changes[0].stat).IsEqualTo(Statistic.Evasion);
|
||||
await Assert.That(changes[0].amount).IsEqualTo(expectedChange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Miracle Eye causes accuracy checks against the target to ignore changes to the
|
||||
/// target's evasion stat stages if its evasion stat stage is greater than 0."
|
||||
/// With a zero or lowered (negative) evasion stat stage the condition does not hold, so the stage
|
||||
/// must be left untouched: a lowered evasion stage remains in effect.
|
||||
/// </summary>
|
||||
[Test, Arguments((sbyte)0), Arguments((sbyte)-1), Arguments((sbyte)-6)]
|
||||
public async Task OnSecondaryEffect_NonPositiveEvasionStage_EvasionStageUnchanged(sbyte evasionStage)
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, target, _, _) = CreateTestSetup(evasionStage);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(target.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ChangeStatBoost")).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia (Generations V to VII): "Miracle Eye will now fail if used against a Pokémon already
|
||||
/// under its effect."
|
||||
/// When the target already has the <see cref="MiracleEyeEffect"/> volatile script, the hit must fail.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetAlreadyUnderEffect_HitFails()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, target, volatileSet, hitData) = CreateTestSetup();
|
||||
volatileSet.Contains<MiracleEyeEffect>().Returns(true);
|
||||
volatileSet.Contains(Arg.Any<StringKey>()).Returns(true);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsTrue();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user