using PkmnLib.Dynamic.Models;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
///
/// Tests for the 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."
///
public class FlameWheelTests
{
///
/// Creates a fully mocked test setup for Flame Wheel tests, initialized with the given burn chance.
///
private static (FlameWheel script, IExecutingMove move, IPokemon user, IPokemon target, IBattleRandom random)
CreateTestSetup(float burnChance = 10f)
{
var script = new FlameWheel();
script.OnInitialize(new Dictionary { { "burn_chance", burnChance } });
var move = Substitute.For();
var user = Substitute.For();
var target = Substitute.For();
var battle = Substitute.For();
var random = Substitute.For();
battle.Random.Returns(random);
move.Battle.Returns(battle);
move.User.Returns(user);
return (script, move, user, target, random);
}
///
/// Helper that checks whether a Pokémon received a SetStatus call for the given status.
///
private static bool ReceivedSetStatus(IPokemon pokemon, string status) =>
pokemon.ReceivedCalls().Any(c =>
c.GetMethodInfo().Name == "SetStatus" && (StringKey)c.GetArguments()[0]! == new StringKey(status));
///
/// Helper that checks whether a Pokémon received a ClearStatus call.
///
private static bool ReceivedClearStatus(IPokemon pokemon) =>
pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ClearStatus");
///
/// 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.
///
[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();
}
///
/// Bulbapedia: "Flame Wheel also has a 10% chance of burning the target."
/// When the effect chance roll fails, the target is not burned.
///
[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();
}
///
/// 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
/// so that effect-chance-modifying effects apply.
///
[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);
}
///
/// Bulbapedia: "Flame Wheel will thaw out the user if it is frozen".
///
[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();
}
///
/// 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.
///
[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();
}
///
/// Technical test: initializing without parameters is invalid, as the script requires a burn chance.
///
[Test]
public async Task OnInitialize_NullParameters_Throws()
{
// Arrange
var script = new FlameWheel();
// Act & Assert
await Assert.That(() => script.OnInitialize(null)).ThrowsExactly();
}
///
/// Technical test: initializing without a "burn_chance" parameter is invalid.
///
[Test]
public async Task OnInitialize_MissingBurnChance_Throws()
{
// Arrange
var script = new FlameWheel();
var parameters = new Dictionary { { "unrelated", 10f } };
// Act & Assert
await Assert.That(() => script.OnInitialize(parameters)).ThrowsExactly();
}
///
/// 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.
///
[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);
}
}