152 lines
5.6 KiB
C#
152 lines
5.6 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Static;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="Moonlight"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Moonlight restores the user's current HP based on the weather in the battle.
|
|
/// During no weather it restores ½ total HP, during harsh sunlight it restores ⅔ total HP, and during other
|
|
/// weather it restores ¼ total HP, rounded down." Generation VI onwards: "When used during strong winds it
|
|
/// restores ½ total HP, rounded down."
|
|
/// </summary>
|
|
public class MoonlightTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup for Moonlight tests. Moonlight targets the user itself, so the
|
|
/// returned Pokémon is used as both the move's user and the target of the secondary effect.
|
|
/// </summary>
|
|
private static (Moonlight moonlight, IExecutingMove move, IPokemon user) CreateTestSetup(uint maxHp,
|
|
string? weatherName)
|
|
{
|
|
var moonlight = new Moonlight();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
|
|
var battle = Substitute.For<IBattle>();
|
|
battle.WeatherName.Returns(weatherName == null ? (StringKey?)null : new StringKey(weatherName));
|
|
var battleData = Substitute.For<IPokemonBattleData>();
|
|
battleData.Battle.Returns(battle);
|
|
|
|
var user = Substitute.For<IPokemon>();
|
|
user.BattleData.Returns(battleData);
|
|
user.BoostedStats.Returns(new StatisticSet<uint>(maxHp, 0, 0, 0, 0, 0));
|
|
move.User.Returns(user);
|
|
|
|
return (moonlight, move, user);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper to extract the heal amount from the user's received Heal calls.
|
|
/// </summary>
|
|
private static uint? GetHealAmount(IPokemon user)
|
|
{
|
|
var call = user.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Heal");
|
|
return call != null ? (uint)call.GetArguments()[0]! : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "During no weather it restores ½ total HP ... rounded down."
|
|
/// </summary>
|
|
[Test, Arguments(100u, 50u), Arguments(99u, 49u), Arguments(255u, 127u)]
|
|
public async Task OnSecondaryEffect_NoWeather_HealsHalfMaxHp(uint maxHp, uint expectedHeal)
|
|
{
|
|
// Arrange
|
|
var (moonlight, move, user) = CreateTestSetup(maxHp, null);
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(GetHealAmount(user)!.Value).IsEqualTo(expectedHeal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "during harsh sunlight it restores ⅔ total HP ... rounded down."
|
|
/// </summary>
|
|
[Test, Arguments(100u, 66u), Arguments(99u, 66u), Arguments(300u, 200u)]
|
|
public async Task OnSecondaryEffect_HarshSunlight_HealsTwoThirdsMaxHp(uint maxHp, uint expectedHeal)
|
|
{
|
|
// Arrange
|
|
var (moonlight, move, user) = CreateTestSetup(maxHp, "harsh_sunlight");
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(GetHealAmount(user)!.Value).IsEqualTo(expectedHeal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "during other weather it restores ¼ total HP, rounded down." Rain, hail and sandstorm all
|
|
/// count as "other weather".
|
|
/// </summary>
|
|
[Test, Arguments("rain", 100u, 25u), Arguments("hail", 100u, 25u), Arguments("sandstorm", 100u, 25u),
|
|
Arguments("rain", 103u, 25u), Arguments("sandstorm", 7u, 1u)]
|
|
public async Task OnSecondaryEffect_OtherWeather_HealsQuarterMaxHp(string weather, uint maxHp, uint expectedHeal)
|
|
{
|
|
// Arrange
|
|
var (moonlight, move, user) = CreateTestSetup(maxHp, weather);
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(GetHealAmount(user)!.Value).IsEqualTo(expectedHeal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation VI onwards): "When used during strong winds it restores ½ total HP, rounded
|
|
/// down."
|
|
/// </summary>
|
|
[Test, Arguments(100u, 50u), Arguments(99u, 49u)]
|
|
public async Task OnSecondaryEffect_StrongWinds_HealsHalfMaxHp(uint maxHp, uint expectedHeal)
|
|
{
|
|
// Arrange
|
|
var (moonlight, move, user) = CreateTestSetup(maxHp, "strong_winds");
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(GetHealAmount(user)!.Value).IsEqualTo(expectedHeal);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Moonlight restores the user's current HP" — the heal is applied to the move's user.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_NoWeather_HealsTheUser()
|
|
{
|
|
// Arrange
|
|
var (moonlight, move, user) = CreateTestSetup(100, null);
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Heal")).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Technical test: without battle data on the user (outside of battle) the secondary effect does nothing
|
|
/// and does not throw.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_UserHasNoBattleData_DoesNotHeal()
|
|
{
|
|
// Arrange
|
|
var moonlight = new Moonlight();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
var user = Substitute.For<IPokemon>();
|
|
user.BattleData.Returns((IPokemonBattleData?)null);
|
|
move.User.Returns(user);
|
|
|
|
// Act
|
|
moonlight.OnSecondaryEffect(move, user, 0);
|
|
|
|
// Assert
|
|
await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Heal")).IsFalse();
|
|
}
|
|
} |