This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="FlameWheel"/> move script.
|
||||
/// Gen VII Bulbapedia behavior: "Flame Wheel will thaw out the user if it is frozen, and then inflict damage
|
||||
/// on the target. Flame Wheel also has a 10% chance of burning the target."
|
||||
/// </summary>
|
||||
public class FlameWheelTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a fully mocked test setup for Flame Wheel tests, initialized with the given burn chance.
|
||||
/// </summary>
|
||||
private static (FlameWheel script, IExecutingMove move, IPokemon user, IPokemon target, IBattleRandom random)
|
||||
CreateTestSetup(float burnChance = 10f)
|
||||
{
|
||||
var script = new FlameWheel();
|
||||
script.OnInitialize(new Dictionary<StringKey, object?> { { "burn_chance", burnChance } });
|
||||
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
var user = Substitute.For<IPokemon>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
|
||||
var battle = Substitute.For<IBattle>();
|
||||
var random = Substitute.For<IBattleRandom>();
|
||||
battle.Random.Returns(random);
|
||||
move.Battle.Returns(battle);
|
||||
move.User.Returns(user);
|
||||
|
||||
return (script, move, user, target, random);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper that checks whether a Pokémon received a SetStatus call for the given status.
|
||||
/// </summary>
|
||||
private static bool ReceivedSetStatus(IPokemon pokemon, string status) =>
|
||||
pokemon.ReceivedCalls().Any(c =>
|
||||
c.GetMethodInfo().Name == "SetStatus" && (StringKey)c.GetArguments()[0]! == new StringKey(status));
|
||||
|
||||
/// <summary>
|
||||
/// Helper that checks whether a Pokémon received a ClearStatus call.
|
||||
/// </summary>
|
||||
private static bool ReceivedClearStatus(IPokemon pokemon) =>
|
||||
pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ClearStatus");
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel also has a 10% chance of burning the target."
|
||||
/// When the effect chance roll succeeds, the target is burned by the user.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_EffectChanceSucceeds_BurnsTarget()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, _, target, random) = CreateTestSetup();
|
||||
random.EffectChance(10f, move, target, 0).Returns(true);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(ReceivedSetStatus(target, "burned")).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel also has a 10% chance of burning the target."
|
||||
/// When the effect chance roll fails, the target is not burned.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_EffectChanceFails_DoesNotBurnTarget()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, _, target, random) = CreateTestSetup();
|
||||
random.EffectChance(10f, move, target, 0).Returns(false);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(ReceivedSetStatus(target, "burned")).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel also has a 10% chance of burning the target."
|
||||
/// The configured burn chance is the one rolled against, and it is rolled through the battle's
|
||||
/// <see cref="IBattleRandom.EffectChance"/> so that effect-chance-modifying effects apply.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_ConfiguredBurnChance_IsPassedToEffectChanceRoll()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, _, target, random) = CreateTestSetup(30f);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
random.Received(1).EffectChance(30f, move, target, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel will thaw out the user if it is frozen".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_UserFrozen_UserIsThawed()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target, _) = CreateTestSetup();
|
||||
user.HasStatus("frozen").Returns(true);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(ReceivedClearStatus(user)).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel will thaw out the user if it is frozen". A user that is not frozen keeps
|
||||
/// whatever status it has; the script must not clear it.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_UserNotFrozen_StatusIsNotCleared()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, user, target, _) = CreateTestSetup();
|
||||
user.HasStatus("frozen").Returns(false);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
await Assert.That(ReceivedClearStatus(user)).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Technical test: initializing without parameters is invalid, as the script requires a burn chance.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnInitialize_NullParameters_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var script = new FlameWheel();
|
||||
|
||||
// Act & Assert
|
||||
await Assert.That(() => script.OnInitialize(null)).ThrowsExactly<Exception>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Technical test: initializing without a "burn_chance" parameter is invalid.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnInitialize_MissingBurnChance_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var script = new FlameWheel();
|
||||
var parameters = new Dictionary<StringKey, object?> { { "unrelated", 10f } };
|
||||
|
||||
// Act & Assert
|
||||
await Assert.That(() => script.OnInitialize(parameters)).ThrowsExactly<Exception>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Flame Wheel also has a 10% chance of burning the target."
|
||||
/// Integration check: initializing the script with Flame Wheel's actual effect parameters from the Gen7
|
||||
/// data results in a 10% burn chance being rolled.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_InitializedWithFlameWheelData_UsesTenPercentBurnChance()
|
||||
{
|
||||
// Arrange
|
||||
var library = LibraryHelpers.LoadLibrary();
|
||||
await Assert.That(library.StaticLibrary.Moves.TryGet("flame_wheel", out var flameWheel)).IsTrue();
|
||||
var (script, move, _, target, random) = CreateTestSetup();
|
||||
|
||||
// Act
|
||||
script.OnInitialize(flameWheel!.SecondaryEffect!.Parameters);
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
random.Received(1).EffectChance(10f, move, target, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user