using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Static; using PkmnLib.Static.Utils; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: Fling inflicts damage; the power of the move is determined by the user's /// held item, the move fails when there is no (flingable) held item, and the item is consumed afterwards. /// public class FlingTests { private static (Fling script, IExecutingMove move, IPokemon target, IPokemon user, IHitData hitData) CreateTestSetup(IItem? heldItem) { var script = new Fling(); var move = Substitute.For(); var target = Substitute.For(); var hitData = Substitute.For(); move.GetHitData(target, 0).Returns(hitData); var user = Substitute.For(); user.HeldItem.Returns(heldItem); move.User.Returns(user); return (script, move, target, user, hitData); } private static IItem CreateItem(ItemCategory category, byte? flingPower) { var item = Substitute.For(); item.Category.Returns(category); item.TryGetAdditionalData(new StringKey("flingPower"), out Arg.Any()).Returns(x => { x[1] = flingPower ?? default(byte); return flingPower.HasValue; }); return item; } /// /// Bulbapedia: "Fling inflicts damage; the power of the move is determined by the user's held item." /// The base power is replaced by the item's fling power (e.g. 10 for Berries, 130 for an Iron Ball). /// [Test, Arguments((byte)10), Arguments((byte)30), Arguments((byte)80), Arguments((byte)130)] public async Task ChangeBasePower_ItemWithFlingPower_BasePowerSetToItemFlingPower(byte flingPower) { // Arrange var item = CreateItem(ItemCategory.MiscItem, flingPower); var (script, move, target, _, hitData) = CreateTestSetup(item); ushort basePower = 1; // Act script.ChangeBasePower(move, target, 0, ref basePower); // Assert await Assert.That(basePower).IsEqualTo((ushort)flingPower); await Assert.That(hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail")).IsFalse(); } /// /// Bulbapedia: "The move fails if the user lacks a held item". Without a held item, the hit is failed /// and the base power is left untouched. /// [Test] public async Task ChangeBasePower_NoHeldItem_MoveFails() { // Arrange var (script, move, target, _, hitData) = CreateTestSetup(null); ushort basePower = 1; // Act script.ChangeBasePower(move, target, 0, ref basePower); // Assert hitData.Received(1).Fail(); await Assert.That(basePower).IsEqualTo((ushort)1); } /// /// Bulbapedia: the move fails if the user carries specific unflingable items, including "TMs, ... /// Poké Balls, Mail, ... Z-Crystals, ... and Mega Stones" and other key items. Items in those /// categories fail the hit even when they define a fling power. /// [Test, Arguments(ItemCategory.Pokeball), Arguments(ItemCategory.Mail), Arguments(ItemCategory.KeyItem), Arguments(ItemCategory.TmHm), Arguments(ItemCategory.FormChanger)] public async Task ChangeBasePower_UnflingableItemCategory_MoveFails(ItemCategory category) { // Arrange var item = CreateItem(category, 30); var (script, move, target, _, hitData) = CreateTestSetup(item); ushort basePower = 1; // Act script.ChangeBasePower(move, target, 0, ref basePower); // Assert hitData.Received(1).Fail(); await Assert.That(basePower).IsEqualTo((ushort)1); } /// /// Bulbapedia: the power of Fling "is determined by the user's held item"; items without a defined /// fling power cannot be flung, so the hit fails. /// [Test] public async Task ChangeBasePower_ItemWithoutFlingPower_MoveFails() { // Arrange var item = CreateItem(ItemCategory.MiscItem, null); var (script, move, target, _, hitData) = CreateTestSetup(item); ushort basePower = 1; // Act script.ChangeBasePower(move, target, 0, ref basePower); // Assert hitData.Received(1).Fail(); await Assert.That(basePower).IsEqualTo((ushort)1); } /// /// Bulbapedia: "After using Fling, the item is consumed". The user's held item is removed for the /// remainder of the battle via . /// [Test] public async Task OnSecondaryEffect_Always_RemovesHeldItemForBattle() { // Arrange var item = CreateItem(ItemCategory.MiscItem, 30); var (script, move, target, user, _) = CreateTestSetup(item); // Act script.OnSecondaryEffect(move, target, 0); // Assert user.Received(1).RemoveHeldItemForBattle(); await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "RemoveHeldItemForBattle")).IsTrue(); } }