using PkmnLib.Dynamic.Models; using PkmnLib.Dynamic.ScriptHandling; using PkmnLib.Dynamic.ScriptHandling.Registry; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Plugin.Gen7.Scripts.Pokemon; using PkmnLib.Plugin.Gen7.Scripts.Side; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: Feint strikes a target that has used Protect or Detect, "lifting the effects /// of Protect or Detect for the remainder of the turn." Generation VI onwards: "Feint hits a target even if /// it is protected by Mat Block, Spiky Shield, King's Shield, Baneful Bunker, Obstruct, Silk Trap, or Burning /// Bulwark and removes that protection for the rest of the turn." and "Feint removes Crafty Shield and Mat /// Block from the target's team." /// public class FeintTests { /// /// Creates a fully mocked test setup where the target has a real as its volatile /// script set. /// private static (Feint script, IExecutingMove move, IPokemon target, IScriptSet volatileSet) CreateTestSetup() { var script = new Feint(); var move = Substitute.For(); var target = Substitute.For(); target.GetScripts().Returns(_ => new ScriptIterator(Array.Empty>())); IScriptSet volatileSet = new ScriptSet(target); target.Volatile.Returns(volatileSet); return (script, move, target, volatileSet); } /// /// Extends the test setup with a battle side that has a real as its volatile /// scripts, so side-wide protections such as can be attached. /// private static IScriptSet AttachSide(IPokemon target) { var side = Substitute.For(); side.GetScripts().Returns(_ => new ScriptIterator(Array.Empty>())); IScriptSet sideScripts = new ScriptSet(side); side.VolatileScripts.Returns(sideScripts); var battleData = Substitute.For(); battleData.BattleSide.Returns(side); target.BattleData.Returns(battleData); return sideScripts; } /// /// Bulbapedia: Feint strikes "a target that has used Protect or Detect during that turn, lifting the /// effects of Protect or Detect for the remainder of the turn." — the target's /// is removed before the hit. /// [Test] public async Task OnBeforeHit_TargetUsedProtect_ProtectionEffectRemoved() { // Arrange var (script, move, target, volatileSet) = CreateTestSetup(); volatileSet.Add(new ProtectionEffectScript()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(volatileSet.Contains(ScriptUtils.ResolveName())).IsFalse(); } /// /// Bulbapedia (Generation V onward): "Feint can now inflict damage even if the target has not used /// Protect or Detect" — with no protection on the target, the hook simply does nothing and does not /// throw. /// [Test] public async Task OnBeforeHit_TargetNotProtected_DoesNothing() { // Arrange var (script, move, target, volatileSet) = CreateTestSetup(); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(volatileSet.Count).IsEqualTo(0); } /// /// Bulbapedia (Generation VI onwards): "Feint hits a target even if it is protected by Mat Block, /// Spiky Shield, King's Shield, Baneful Bunker, Obstruct, Silk Trap, or Burning Bulwark and removes that /// protection for the rest of the turn." — a target under Spiky Shield has its /// removed. /// [Test] public async Task OnBeforeHit_TargetUnderSpikyShield_ProtectionEffectRemoved() { // Arrange var (script, move, target, volatileSet) = CreateTestSetup(); volatileSet.Add(new SpikyShieldEffect()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(volatileSet.Contains(ScriptUtils.ResolveName())).IsFalse(); } /// /// Bulbapedia (Generation VI onwards): "Feint hits a target even if it is protected by Mat Block, /// Spiky Shield, King's Shield, Baneful Bunker, Obstruct, Silk Trap, or Burning Bulwark and removes that /// protection for the rest of the turn." — a target under King's Shield has its /// effect removed. /// [Test] public async Task OnBeforeHit_TargetUnderKingsShield_ProtectionEffectRemoved() { // Arrange var (script, move, target, volatileSet) = CreateTestSetup(); volatileSet.Add(new KingsShieldEffect()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(volatileSet.Contains(ScriptUtils.ResolveName())).IsFalse(); } /// /// Bulbapedia (Generation VI onwards): "Feint hits a target even if it is protected by Mat Block, /// Spiky Shield, King's Shield, Baneful Bunker, Obstruct, Silk Trap, or Burning Bulwark and removes that /// protection for the rest of the turn." — a target under Baneful Bunker has its /// removed. /// [Test] public async Task OnBeforeHit_TargetUnderBanefulBunker_ProtectionEffectRemoved() { // Arrange var (script, move, target, volatileSet) = CreateTestSetup(); volatileSet.Add(new BanefulBunkerEffect()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(volatileSet.Contains(ScriptUtils.ResolveName())).IsFalse(); } /// /// Bulbapedia (Generation VI onwards): "Feint removes Crafty Shield and Mat Block from the target's /// team." — the is removed from the target's side. /// [Test] public async Task OnBeforeHit_CraftyShieldOnTargetSide_SideEffectRemoved() { // Arrange var (script, move, target, _) = CreateTestSetup(); var sideScripts = AttachSide(target); sideScripts.Add(new CraftyShieldEffect()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(sideScripts.Contains(ScriptUtils.ResolveName())).IsFalse(); } /// /// Bulbapedia (Generation VI onwards): "Feint removes Crafty Shield and Mat Block from the target's /// team." — the is removed from the target's side. /// [Test] public async Task OnBeforeHit_MatBlockOnTargetSide_SideEffectRemoved() { // Arrange var (script, move, target, _) = CreateTestSetup(); var sideScripts = AttachSide(target); sideScripts.Add(new MatBlockEffect()); // Act script.OnBeforeHit(move, target, 0); // Assert await Assert.That(sideScripts.Contains(ScriptUtils.ResolveName())).IsFalse(); } }