using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Static.Species; using PkmnLib.Static.Utils; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: "Entrainment changes the target's Ability to match the user's." It fails /// if both Pokémon already share the same Ability, if the target's Ability cannot be changed (e.g. /// Truant, Multitype, Stance Change, Comatose, Disguise), or if the user's Ability cannot be copied /// (e.g. Trace, Illusion, Imposter, Power Construct). /// public class EntrainmentTests { /// /// Creates a mocked ability that reports the given flags as set. /// private static IAbility CreateAbility(params string[] flags) { var ability = Substitute.For(); foreach (var flag in flags) ability.HasFlag(new StringKey(flag)).Returns(true); return ability; } private static (Entrainment script, IExecutingMove move, IPokemon target, IHitData hitData) CreateTestSetup( IAbility? userAbility, IAbility? targetAbility) { var script = new Entrainment(); var move = Substitute.For(); var target = Substitute.For(); var hitData = Substitute.For(); move.GetHitData(target, 0).Returns(hitData); var user = Substitute.For(); user.ActiveAbility.Returns(userAbility); move.User.Returns(user); target.ActiveAbility.Returns(targetAbility); return (script, move, target, hitData); } /// /// Bulbapedia: "Entrainment changes the target's Ability to match the user's." /// [Test] public void OnSecondaryEffect_DifferentAbilities_ChangesTargetAbilityToUsers() { // Arrange var userAbility = CreateAbility(); var (script, move, target, hitData) = CreateTestSetup(userAbility, CreateAbility()); // Act script.OnSecondaryEffect(move, target, 0); // Assert target.Received(1).ChangeAbility(userAbility); hitData.DidNotReceive().Fail(); } /// /// Bulbapedia: "The move fails if both Pokémon already share the same Ability." /// [Test] public void OnSecondaryEffect_SameAbility_FailsHit() { // Arrange var sharedAbility = CreateAbility(); var (script, move, target, hitData) = CreateTestSetup(sharedAbility, sharedAbility); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); target.DidNotReceiveWithAnyArgs().ChangeAbility(default!); } /// /// Bulbapedia: "The move fails if the user has: Trace, Forecast, Flower Gift, Zen Mode, Illusion, /// Imposter, [...]" — abilities that cannot be copied prevent Entrainment from working. /// [Test] public void OnSecondaryEffect_UserAbilityCantBeCopied_FailsHit() { // Arrange var userAbility = CreateAbility("cant_be_copied"); var (script, move, target, hitData) = CreateTestSetup(userAbility, CreateAbility()); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); target.DidNotReceiveWithAnyArgs().ChangeAbility(default!); } /// /// Bulbapedia: "The move cannot affect Pokémon with these Abilities: Truant, Multitype, Stance /// Change, [...]" — a target whose ability cannot be changed prevents Entrainment from working. /// [Test] public void OnSecondaryEffect_TargetAbilityCantBeChanged_FailsHit() { // Arrange var targetAbility = CreateAbility("cant_be_changed"); var (script, move, target, hitData) = CreateTestSetup(CreateAbility(), targetAbility); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); target.DidNotReceiveWithAnyArgs().ChangeAbility(default!); } /// /// Bulbapedia: "Entrainment changes the target's Ability to match the user's" — without a user /// ability there is nothing to copy, so the move fails. /// [Test] public void OnSecondaryEffect_UserHasNoAbility_FailsHit() { // Arrange var (script, move, target, hitData) = CreateTestSetup(null, CreateAbility()); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); target.DidNotReceiveWithAnyArgs().ChangeAbility(default!); } /// /// Technical test: a target without an active ability cannot have it validated for replacement, so /// the move fails rather than throwing. /// [Test] public void OnSecondaryEffect_TargetHasNoAbility_FailsHit() { // Arrange var (script, move, target, hitData) = CreateTestSetup(CreateAbility(), null); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.Received(1).Fail(); target.DidNotReceiveWithAnyArgs().ChangeAbility(default!); } }