This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Static;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="GuardSwap"/> move script.
|
||||
/// Gen VII Bulbapedia behavior: "Guard Swap switches the user's Defense stat stages and Special Defense
|
||||
/// stat stages with the target's Defense stat stages and Special Defense stat stages."
|
||||
/// </summary>
|
||||
public class GuardSwapTests
|
||||
{
|
||||
private static (GuardSwap script, IExecutingMove move, IPokemon user, IPokemon target) CreateTestSetup(
|
||||
sbyte userDefense, sbyte userSpecialDefense, sbyte targetDefense, sbyte targetSpecialDefense)
|
||||
{
|
||||
var script = new GuardSwap();
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
|
||||
var user = Substitute.For<IPokemon>();
|
||||
user.StatBoost.Returns(new StatBoostStatisticSet(0, 0, userDefense, 0, userSpecialDefense, 0));
|
||||
move.User.Returns(user);
|
||||
|
||||
var target = Substitute.For<IPokemon>();
|
||||
target.StatBoost.Returns(new StatBoostStatisticSet(0, 0, targetDefense, 0, targetSpecialDefense, 0));
|
||||
|
||||
return (script, move, user, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to extract the arguments of the received ChangeStatBoost call for the given statistic, or
|
||||
/// null when that stat was not changed. Received-call inspection is used instead of NSubstitute
|
||||
/// argument matchers because the trailing EventBatchId parameter cannot be bound by <c>Arg.Any</c>.
|
||||
/// </summary>
|
||||
private static object?[]? GetStatBoostArgs(IPokemon pokemon, Statistic stat) =>
|
||||
pokemon.ReceivedCalls().Where(c => c.GetMethodInfo().Name == "ChangeStatBoost").Select(c => c.GetArguments())
|
||||
.FirstOrDefault(args => (Statistic)args[0]! == stat);
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Guard Swap switches the user's Defense stat stages ... with the target's Defense stat
|
||||
/// stages." The user at +2 Defense and the target at -1 Defense must end up at -1 and +2
|
||||
/// respectively, so the user is changed by -3 and the target by +3.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_DifferentDefenseStages_StagesAreSwapped()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target) = CreateTestSetup(2, 0, -1, 0);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var userArgs = GetStatBoostArgs(user, Statistic.Defense);
|
||||
var targetArgs = GetStatBoostArgs(target, Statistic.Defense);
|
||||
await Assert.That(userArgs).IsNotNull();
|
||||
await Assert.That((sbyte)userArgs![1]!).IsEqualTo((sbyte)-3);
|
||||
await Assert.That(targetArgs).IsNotNull();
|
||||
await Assert.That((sbyte)targetArgs![1]!).IsEqualTo((sbyte)3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the swap also covers the "Special Defense stat stages". The user at -2 Special Defense
|
||||
/// and the target at +3 must end up at +3 and -2 respectively, so the user is changed by +5 and the
|
||||
/// target by -5.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_DifferentSpecialDefenseStages_StagesAreSwapped()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target) = CreateTestSetup(0, -2, 0, 3);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var userArgs = GetStatBoostArgs(user, Statistic.SpecialDefense);
|
||||
var targetArgs = GetStatBoostArgs(target, Statistic.SpecialDefense);
|
||||
await Assert.That(userArgs).IsNotNull();
|
||||
await Assert.That((sbyte)userArgs![1]!).IsEqualTo((sbyte)5);
|
||||
await Assert.That(targetArgs).IsNotNull();
|
||||
await Assert.That((sbyte)targetArgs![1]!).IsEqualTo((sbyte)-5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the swap is unconditional — the change is applied with force so clamping or
|
||||
/// prevention effects cannot block the exchange of stages.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_Always_ChangesAreForced()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target) = CreateTestSetup(2, 0, -1, 0);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var userArgs = GetStatBoostArgs(user, Statistic.Defense);
|
||||
var targetArgs = GetStatBoostArgs(target, Statistic.Defense);
|
||||
await Assert.That((bool)userArgs![3]!).IsTrue(); // forced
|
||||
await Assert.That((bool)targetArgs![3]!).IsTrue(); // forced
|
||||
await Assert.That((bool)userArgs[2]!).IsTrue(); // self-inflicted for the user
|
||||
await Assert.That((bool)targetArgs[2]!).IsFalse(); // not self-inflicted for the target
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: only the "Defense stat stages and Special Defense stat stages" are switched — the
|
||||
/// other stat stages are left untouched.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_Always_OtherStagesUnchanged()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target) = CreateTestSetup(2, -2, -1, 3);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(GetStatBoostArgs(user, Statistic.Attack)).IsNull();
|
||||
await Assert.That(GetStatBoostArgs(user, Statistic.SpecialAttack)).IsNull();
|
||||
await Assert.That(GetStatBoostArgs(user, Statistic.Speed)).IsNull();
|
||||
await Assert.That(GetStatBoostArgs(target, Statistic.Attack)).IsNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When both Pokémon have equal stages, swapping is a net-zero change for both sides.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_EqualStages_ChangeIsZero()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target) = CreateTestSetup(1, 2, 1, 2);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
var userDefenseArgs = GetStatBoostArgs(user, Statistic.Defense);
|
||||
var userSpecialDefenseArgs = GetStatBoostArgs(user, Statistic.SpecialDefense);
|
||||
await Assert.That((sbyte)userDefenseArgs![1]!).IsEqualTo((sbyte)0);
|
||||
await Assert.That((sbyte)userSpecialDefenseArgs![1]!).IsEqualTo((sbyte)0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user