using PkmnLib.Dynamic.Events; 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: "Incinerate inflicts damage to all adjacent opponents. The move destroys any /// Berries held by hit Pokémon". Generation VI onwards: "The move now also destroys Gems." /// public class IncinerateTests { /// /// Creates a fully mocked test setup for Incinerate tests, with the target holding the given item /// (nothing when null). /// private static (Incinerate script, IExecutingMove move, IPokemon target, IHitData hitData, EventHook eventHook) CreateTestSetup(IItem? heldItem) { var script = new Incinerate(); var move = Substitute.For(); var target = Substitute.For(); var hitData = Substitute.For(); move.GetHitData(target, 0).Returns(hitData); var eventHook = new EventHook(); var battle = Substitute.For(); battle.EventHook.Returns(eventHook); move.Battle.Returns(battle); target.HeldItem.Returns(heldItem); if (heldItem != null) { target.TryStealHeldItem(out Arg.Any()).Returns(x => { x[0] = heldItem; return true; }); } return (script, move, target, hitData, eventHook); } /// /// Creates a substitute held item with the given name and category. /// private static IItem CreateItem(string name, ItemCategory category) { var item = Substitute.For(); item.Name.Returns(new StringKey(name)); item.Category.Returns(category); return item; } /// /// Helper to check whether the target's held item was taken away. /// private static bool ItemWasRemoved(IPokemon pokemon) => pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "TryStealHeldItem"); /// /// Bulbapedia: "The move destroys any Berries held by hit Pokémon." A held Berry is removed from the /// target. /// [Test] public async Task OnSecondaryEffect_TargetHoldsBerry_BerryIsRemoved() { // Arrange var berry = CreateItem("oran_berry", ItemCategory.Berry); var (script, move, target, _, _) = CreateTestSetup(berry); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(ItemWasRemoved(target)).IsTrue(); } /// /// Bulbapedia: "The move destroys any Berries held by hit Pokémon" — the destruction is announced /// through a so the battle log can show it. /// [Test] public async Task OnSecondaryEffect_TargetHoldsBerry_FiresItemIncineratedDialogEvent() { // Arrange var berry = CreateItem("oran_berry", ItemCategory.Berry); var (script, move, target, _, eventHook) = CreateTestSetup(berry); DialogEvent? captured = null; eventHook.Handler += (_, args) => { if (args is DialogEvent dialogEvent) captured = dialogEvent; }; // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(captured).IsNotNull(); await Assert.That(captured!.Message).IsEqualTo("item_incinerated"); } /// /// Bulbapedia: only Berries (and, from Gen VI, Gems) are destroyed. A regular held item is left alone. /// [Test] public async Task OnSecondaryEffect_TargetHoldsRegularItem_ItemIsNotRemoved() { // Arrange var item = CreateItem("leftovers", ItemCategory.MiscItem); var (script, move, target, _, _) = CreateTestSetup(item); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(ItemWasRemoved(target)).IsFalse(); } /// /// Bulbapedia (Generation VI onwards): "The move now also destroys Gems." A held Gem is removed from /// the target. /// [Test] public async Task OnSecondaryEffect_TargetHoldsGem_GemIsRemoved() { // Arrange var gem = CreateItem("normal_gem", ItemCategory.MiscItem); var (script, move, target, _, _) = CreateTestSetup(gem); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(ItemWasRemoved(target)).IsTrue(); } /// /// Bulbapedia: "Incinerate inflicts damage to all adjacent opponents." Destroying a Berry is a bonus /// effect: against a target holding nothing the move still simply deals its damage, it does not fail. /// [Test] public void OnSecondaryEffect_TargetHoldsNoItem_HitIsNotMarkedAsFailed() { // Arrange var (script, move, target, hitData, _) = CreateTestSetup(null); // Act script.OnSecondaryEffect(move, target, 0); // Assert hitData.DidNotReceive().Fail(); } }