using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Static; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: "The user transfers its held item to the target. It fails if the user has no /// held item, the target already has a held item, or the target is behind a substitute. [...] Items given away /// in Trainer battles return to the original Pokémon after the battle." /// public class BestowTests { private static (Bestow script, IExecutingMove move, IPokemon user, IPokemon target, IHitData hitData) CreateTestSetup(IItem? userItem, IItem? targetItem) { var script = new Bestow(); var move = Substitute.For(); var target = Substitute.For(); var hitData = Substitute.For(); move.GetHitData(target, 0).Returns(hitData); target.HeldItem.Returns(targetItem); var user = Substitute.For(); user.HeldItem.Returns(userItem); user.RemoveHeldItemForBattle().Returns(userItem); move.User.Returns(user); return (script, move, user, target, hitData); } /// /// Bulbapedia: "The user transfers its held item to the target." /// The target ends up holding the user's item. /// [Test] public void OnSecondaryEffect_TargetHasNoItem_TargetReceivesUsersItem() { // Arrange var userItem = Substitute.For(); var (script, move, _, target, _) = CreateTestSetup(userItem, null); // Act script.OnSecondaryEffect(move, target, 0); // Assert _ = target.Received(1).ForceSetHeldItem(userItem); } /// /// Bulbapedia: "The user transfers its held item to the target." /// A successful transfer does not fail the move. /// [Test] public void OnSecondaryEffect_TargetHasNoItem_MoveDoesNotFail() { // Arrange var userItem = Substitute.For(); var (script, move, _, target, hitData) = CreateTestSetup(userItem, null); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.DidNotReceive().Fail(); } /// /// Bulbapedia: "Items given away in Trainer battles return to the original Pokémon after the battle." /// The item is taken from the user through , which only /// removes the item for the duration of the battle. /// [Test] public void OnSecondaryEffect_TargetHasNoItem_UserItemIsRemovedForBattleOnly() { // Arrange var userItem = Substitute.For(); var (script, move, user, target, _) = CreateTestSetup(userItem, null); // Act script.OnSecondaryEffect(move, target, 0); // Assert user.Received(1).RemoveHeldItemForBattle(); } /// /// Bulbapedia: "It fails if the user has no held item". /// [Test] public void OnSecondaryEffect_UserHasNoHeldItem_MoveFails() { // Arrange var (script, move, _, target, hitData) = CreateTestSetup(null, null); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); } /// /// Bulbapedia: "It fails if the user has no held item". /// When the move fails, no item is given to the target. /// [Test] public void OnSecondaryEffect_UserHasNoHeldItem_TargetDoesNotReceiveAnItem() { // Arrange var (script, move, _, target, _) = CreateTestSetup(null, null); // Act script.OnSecondaryEffect(move, target, 0); // Assert _ = target.DidNotReceive().ForceSetHeldItem(Arg.Any()); } /// /// Bulbapedia: "It fails if [...] the target already has a held item". /// [Test] public void OnSecondaryEffect_TargetAlreadyHasHeldItem_MoveFails() { // Arrange var (script, move, _, target, hitData) = CreateTestSetup(Substitute.For(), Substitute.For()); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); } /// /// Bulbapedia: "It fails if [...] the target already has a held item". /// The target's own held item is left untouched by the failed move. /// [Test] public void OnSecondaryEffect_TargetAlreadyHasHeldItem_TargetItemIsNotReplaced() { // Arrange var (script, move, _, target, _) = CreateTestSetup(Substitute.For(), Substitute.For()); // Act script.OnSecondaryEffect(move, target, 0); // Assert target.DidNotReceive().ForceSetHeldItem(Arg.Any()); } /// /// Bulbapedia: "It fails if [...] the target already has a held item". /// A failed Bestow must not cost the user its held item: the item is either never taken from the user, or /// it is given back after the failure check. /// [Test] public async Task OnSecondaryEffect_TargetAlreadyHasHeldItem_UserKeepsItsHeldItem() { // Arrange var userItem = Substitute.For(); var (script, move, user, target, _) = CreateTestSetup(userItem, Substitute.For()); // Act script.OnSecondaryEffect(move, target, 0); // Assert - the user still holds its item: it was either never removed, or restored after the failure. var removed = user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "RemoveHeldItemForBattle"); var restored = user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ForceSetHeldItem" && ReferenceEquals(c.GetArguments()[0], userItem)); await Assert.That(!removed || restored).IsTrue(); } }