using PkmnLib.Dynamic.Libraries;
using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Plugin.Gen7.Scripts.Battle;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Static;
using PkmnLib.Static.Libraries;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
///
/// Tests for the move.
///
public class JudgementTests
{
public record TestCaseData(string? ItemName, string ExpectedTypeName)
{
public override string ToString() => $"Judgement {ItemName ?? "None"} => {ExpectedTypeName}";
}
public static IEnumerable> ChangeMoveTypeData()
{
yield return () => new TestCaseData("draco_plate", "dragon");
yield return () => new TestCaseData("dread_plate", "dark");
yield return () => new TestCaseData("earth_plate", "ground");
yield return () => new TestCaseData("fist_plate", "fighting");
yield return () => new TestCaseData("flame_plate", "fire");
yield return () => new TestCaseData("icicle_plate", "ice");
yield return () => new TestCaseData("insect_plate", "bug");
yield return () => new TestCaseData("iron_plate", "steel");
yield return () => new TestCaseData("meadow_plate", "grass");
yield return () => new TestCaseData("mind_plate", "psychic");
yield return () => new TestCaseData("pixie_plate", "fairy");
yield return () => new TestCaseData("sky_plate", "flying");
yield return () => new TestCaseData("splash_plate", "water");
yield return () => new TestCaseData("spooky_plate", "ghost");
yield return () => new TestCaseData("stone_plate", "rock");
yield return () => new TestCaseData("toxic_plate", "poison");
yield return () => new TestCaseData("zap_plate", "electric");
}
private static TypeLibrary CreateTypeLibrary()
{
var typeLibrary = new TypeLibrary();
typeLibrary.RegisterType("normal");
typeLibrary.RegisterType("fighting");
typeLibrary.RegisterType("flying");
typeLibrary.RegisterType("poison");
typeLibrary.RegisterType("ground");
typeLibrary.RegisterType("rock");
typeLibrary.RegisterType("bug");
typeLibrary.RegisterType("ghost");
typeLibrary.RegisterType("steel");
typeLibrary.RegisterType("fire");
typeLibrary.RegisterType("water");
typeLibrary.RegisterType("grass");
typeLibrary.RegisterType("electric");
typeLibrary.RegisterType("psychic");
typeLibrary.RegisterType("ice");
typeLibrary.RegisterType("dragon");
typeLibrary.RegisterType("dark");
typeLibrary.RegisterType("fairy");
return typeLibrary;
}
private static (Judgement Script, IExecutingMove Move, IBattlePokemon Target) CreateTestSetup(string? itemName)
{
var move = Substitute.For();
var target = Substitute.For();
var user = Substitute.For();
var dynamicLibrary = Substitute.For();
var staticLibrary = Substitute.For();
target.Library.Returns(dynamicLibrary);
dynamicLibrary.StaticLibrary.Returns(staticLibrary);
staticLibrary.Types.Returns(CreateTypeLibrary());
move.User.Returns(user);
if (itemName != null)
{
var item = Substitute.For();
item.Name.Returns(new StringKey(itemName));
user.HeldItem.Returns(item);
}
else
{
user.HeldItem.Returns((IItem?)null);
}
return (new Judgement(), move, target);
}
///
/// Bulbapedia: "The type of Judgment depends on the type of Plate held by the user".
///
[Test, MethodDataSource(nameof(ChangeMoveTypeData))]
public async Task ChangeMoveType_UserHoldingPlate_ChangesMoveType(TestCaseData test)
{
// Arrange
var (script, move, target) = CreateTestSetup(test.ItemName);
TypeIdentifier? typeIdentifier = new TypeIdentifier(1, "normal");
// Act
script.ChangeMoveType(move, target, 0, ref typeIdentifier);
// Assert
await Assert.That(typeIdentifier!.Value.Name.ToString()).IsEqualTo(test.ExpectedTypeName);
}
///
/// Bulbapedia: "being Normal-type if there is no held Plate". Without a held item the move type
/// is left unchanged.
///
[Test]
public async Task ChangeMoveType_UserNotHoldingItem_MoveTypeUnchanged()
{
// Arrange
var (script, move, target) = CreateTestSetup(null);
TypeIdentifier? typeIdentifier = new TypeIdentifier(1, "normal");
// Act
script.ChangeMoveType(move, target, 0, ref typeIdentifier);
// Assert
await Assert.That(typeIdentifier!.Value.Name.ToString()).IsEqualTo("normal");
}
///
/// Bulbapedia: "being Normal-type if there is no held Plate". A held item that is not a Plate
/// leaves the move type unchanged.
///
[Test]
public async Task ChangeMoveType_UserHoldingNonPlateItem_MoveTypeUnchanged()
{
// Arrange
var (script, move, target) = CreateTestSetup("oran_berry");
TypeIdentifier? typeIdentifier = new TypeIdentifier(1, "normal");
// Act
script.ChangeMoveType(move, target, 0, ref typeIdentifier);
// Assert
await Assert.That(typeIdentifier!.Value.Name.ToString()).IsEqualTo("normal");
}
///
/// Bulbapedia: "Judgment's type is unaffected by Z-Crystals held by the user, remaining a
/// Normal-type move."
///
[Test]
public async Task ChangeMoveType_UserHoldingZCrystal_MoveTypeRemainsNormal()
{
// Arrange
var (script, move, target) = CreateTestSetup("firium_z");
TypeIdentifier? typeIdentifier = new TypeIdentifier(1, "normal");
// Act
script.ChangeMoveType(move, target, 0, ref typeIdentifier);
// Assert
await Assert.That(typeIdentifier!.Value.Name.ToString()).IsEqualTo("normal");
}
///
/// Bulbapedia: "If Magic Room is in effect, Judgment's type will always be Normal regardless of
/// the Plate held." With on the battle, a held Plate must not
/// change the move type.
///
[Test]
public async Task ChangeMoveType_MagicRoomInEffect_MoveTypeRemainsNormal()
{
// Arrange
var (script, move, target) = CreateTestSetup("flame_plate");
var battle = Substitute.For();
battle.GetScripts().Returns(_ => new ScriptIterator(new List>()));
var battleVolatile = new ScriptSet(battle);
battleVolatile.Add(new MagicRoomEffect());
battle.Volatile.Returns(battleVolatile);
move.Battle.Returns(battle);
TypeIdentifier? typeIdentifier = new TypeIdentifier(1, "normal");
// Act
script.ChangeMoveType(move, target, 0, ref typeIdentifier);
// Assert
await Assert.That(typeIdentifier!.Value.Name.ToString()).IsEqualTo("normal");
}
}