diff --git a/src/test/moves/fell_stinger.test.ts b/src/test/moves/fell_stinger.test.ts index 596a4aa8db0..85d22fb17cb 100644 --- a/src/test/moves/fell_stinger.test.ts +++ b/src/test/moves/fell_stinger.test.ts @@ -1,5 +1,5 @@ import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import GameManager from "../utils/gameManager"; import { Species } from "#enums/species"; import { Abilities } from "#enums/abilities"; @@ -7,6 +7,7 @@ import { Moves } from "#enums/moves"; import { Stat } from "#enums/stat"; import { StatusEffect } from "#app/enums/status-effect"; import { WeatherType } from "#app/enums/weather-type"; +import { allMoves } from "#app/data/move"; describe("Moves - Fell Stinger", () => { @@ -27,21 +28,27 @@ describe("Moves - Fell Stinger", () => { game = new GameManager(phaserGame); game.override.battleType("single") - .moveset([ Moves.FELL_STINGER ]) - .startingLevel(50); + .moveset([ + Moves.FELL_STINGER, + Moves.SALT_CURE, + Moves.BIND, + Moves.LEECH_SEED + ]) + .startingLevel(50) + .disableCrits(); game.override.enemyAbility(Abilities.STURDY) .enemySpecies(Species.HYPNO) - .enemyLevel(5) - .enemyHeldItems([]); + .enemyMoveset([ Moves.SPLASH ]) + .enemyLevel(5); game.override.weather(WeatherType.NONE); }); - it("should not grant stat boost when opponent gets KO'd by recoil", async () => { + it("should not grant stat boost if opponent gets KO'd by recoil", async () => { game.override.enemyMoveset([ Moves.DOUBLE_EDGE ]); - await game.classicMode.startBattle([ Species.LEAVANNY ]); + await game.classicMode.startBattle([ Species.LEAVANNY ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.FELL_STINGER); @@ -50,12 +57,12 @@ describe("Moves - Fell Stinger", () => { expect(leadPokemon.getStatStage(Stat.ATK) === 0); // Attack stage should still be at 0 }); - it("should not grant stat boost when enemy is KO'd by status effect", async () => { + it("should not grant stat boost if enemy is KO'd by status effect", async () => { game.override .enemyMoveset(Moves.SPLASH) .enemyStatusEffect(StatusEffect.BURN); - await game.classicMode.startBattle([ Species.LEAVANNY ]); + await game.classicMode.startBattle([ Species.LEAVANNY ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.FELL_STINGER); @@ -64,10 +71,10 @@ describe("Moves - Fell Stinger", () => { expect(leadPokemon.getStatStage(Stat.ATK) === 0); // Attack stage should still be at 0 }); - it("should not grant stat boost when enemy is KO'd by damaging weather", async () => { + it("should not grant stat boost if enemy is KO'd by damaging weather", async () => { game.override.weather(WeatherType.HAIL); - await game.classicMode.startBattle([ Species.LEAVANNY ]); + await game.classicMode.startBattle([ Species.LEAVANNY ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.FELL_STINGER); @@ -77,13 +84,13 @@ describe("Moves - Fell Stinger", () => { expect(leadPokemon.getStatStage(Stat.ATK) === 0); // Attack stage should still be at 0 }); - it("should not grant stat boost when enemy is KO'd by Dry Skin + Harsh Sunlight", async () => { + it("should not grant stat boost if enemy is KO'd by Dry Skin + Harsh Sunlight", async () => { game.override .enemyPassiveAbility(Abilities.STURDY) .enemyAbility(Abilities.DRY_SKIN) .weather(WeatherType.HARSH_SUN); - await game.challengeMode.startBattle([ Species.LEAVANNY ]); + await game.challengeMode.startBattle([ Species.LEAVANNY ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.FELL_STINGER); @@ -99,7 +106,6 @@ describe("Moves - Fell Stinger", () => { .enemyHeldItems([{ name: "REVIVER_SEED" }]); await game.classicMode.startBattle([ Species.LEAVANNY ]); - const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.FELL_STINGER); @@ -107,15 +113,89 @@ describe("Moves - Fell Stinger", () => { expect(leadPokemon.getStatStage(Stat.ATK) === 0); // Attack stage should still be at 0 }); - it("should grant stat boost when enemy dies directly to hit", async () => { - game.override.enemyAbility(Abilities.KLUTZ); - await game.challengeMode.startBattle([ Species.LEAVANNY ]); + it("should not grant stat boost if enemy is KO'd by Salt Cure", async () => { + game.override.battleType("double") + .startingLevel(5); + const saltCure = allMoves[Moves.SALT_CURE]; + const fellStinger = allMoves[Moves.FELL_STINGER]; + vi.spyOn(saltCure, "accuracy", "get").mockReturnValue(100); + vi.spyOn(fellStinger, "power", "get").mockReturnValue(50000); + await game.classicMode.startBattle([ Species.LEAVANNY ]); const leadPokemon = game.scene.getPlayerPokemon()!; + const leftEnemy = game.scene.getEnemyField()[0]!; + + // Turn 1: set Salt Cure, enemy splashes and does nothing + game.move.select(Moves.SALT_CURE, 0, leftEnemy.getBattlerIndex()); + + // Turn 2: enemy Endures Fell Stinger, then dies to Salt Cure + await game.toNextTurn(); + expect(leftEnemy.isFainted()).toBe(false); + leftEnemy.heal(leftEnemy.getMaxHp()); + game.move.select(Moves.FELL_STINGER); + await game.toNextTurn(); + + expect(leftEnemy.isFainted()).toBe(true); + expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("should not grant stat boost if enemy dies to Bind or a similar effect", async () => { + game.override.battleType("double") + .startingLevel(5); + vi.spyOn(allMoves[Moves.BIND], "accuracy", "get").mockReturnValue(100); + vi.spyOn(allMoves[Moves.FELL_STINGER], "power", "get").mockReturnValue(50000); + + await game.classicMode.startBattle([ Species.LEAVANNY ]); + const leadPokemon = game.scene.getPlayerPokemon()!; + const leftEnemy = game.scene.getEnemyField()[0]!; + + // Turn 1: set Bind, enemy splashes and does nothing + game.move.select(Moves.BIND, 0, leftEnemy.getBattlerIndex()); + + // Turn 2: enemy Endures Fell Stinger, then dies to Bind + await game.toNextTurn(); + expect(leftEnemy.isFainted()).toBe(false); + leftEnemy.heal(leftEnemy.getMaxHp()); + game.move.select(Moves.FELL_STINGER, 0, leftEnemy.getBattlerIndex()); + await game.toNextTurn(); + + expect(leftEnemy.isFainted()).toBe(true); + expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("should not grant stat boost if enemy dies to Leech Seed", async () => { + game.override.battleType("double") + .startingLevel(5); + vi.spyOn(allMoves[Moves.LEECH_SEED], "accuracy", "get").mockReturnValue(100); + vi.spyOn(allMoves[Moves.FELL_STINGER], "power", "get").mockReturnValue(50000); + + await game.classicMode.startBattle([ Species.LEAVANNY ]); + const leadPokemon = game.scene.getPlayerPokemon()!; + const leftEnemy = game.scene.getEnemyField()[0]!; + + // Turn 1: set Bind, enemy splashes and does nothing + game.move.select(Moves.LEECH_SEED, 0, leftEnemy.getBattlerIndex()); + + // Turn 2: enemy Endures Fell Stinger, then dies to Bind + await game.toNextTurn(); + expect(leftEnemy.isFainted()).toBe(false); + leftEnemy.heal(leftEnemy.getMaxHp()); + game.move.select(Moves.FELL_STINGER, 0, leftEnemy.getBattlerIndex()); + await game.toNextTurn(); + + expect(leftEnemy.isFainted()).toBe(true); + expect(leadPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("should grant stat boost if enemy dies directly to hit", async () => { + game.override.enemyAbility(Abilities.KLUTZ); + + await game.classicMode.startBattle([ Species.LEAVANNY ]); + const leadPokemon = game.scene.getPlayerPokemon(); game.move.select(Moves.FELL_STINGER); - await game.phaseInterceptor.to("VictoryPhase"); + await game.phaseInterceptor.to("TurnEndPhase"); - expect(leadPokemon.getStatStage(Stat.ATK) === 3); // Attack stage should have risen to 3 + expect(leadPokemon?.getStatStage(Stat.ATK)).toBe(3); // Attack stage should have risen to 3 }); });