From dbda6e8d4765110a0b38d234675a6c4c4fdb2378 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:14:46 -0500 Subject: [PATCH] Create unified test file for galvanize, pixilate, and refrigerate --- .../galvanize-refrigerate-pixilate.test.ts | 158 ++++++++++++++++++ test/abilities/galvanize.test.ts | 131 --------------- test/moves/tera_blast.test.ts | 16 +- 3 files changed, 172 insertions(+), 133 deletions(-) create mode 100644 test/abilities/galvanize-refrigerate-pixilate.test.ts delete mode 100644 test/abilities/galvanize.test.ts diff --git a/test/abilities/galvanize-refrigerate-pixilate.test.ts b/test/abilities/galvanize-refrigerate-pixilate.test.ts new file mode 100644 index 00000000000..c5803dc550b --- /dev/null +++ b/test/abilities/galvanize-refrigerate-pixilate.test.ts @@ -0,0 +1,158 @@ +import { BattlerIndex } from "#app/battle"; +import { allMoves } from "#app/data/moves/move"; +import { PokemonType } from "#enums/pokemon-type"; +import { Abilities } from "#app/enums/abilities"; +import { Moves } from "#app/enums/moves"; +import { Species } from "#app/enums/species"; +import { HitResult } from "#app/field/pokemon"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +/** + * Tests for abilities that change the type of normal moves to + * a different type and boost their power + * + * Includes + * - Galvanize + * - Pixilate + * - Refrigerate + */ + +describe.each([ + { ab: Abilities.GALVANIZE, ab_name: "Galvanize", ty: PokemonType.ELECTRIC, ty_name: "electric" }, + { ab: Abilities.PIXILATE, ab_name: "Pixilate", ty: PokemonType.FAIRY, ty_name: "fairy" }, + { ab: Abilities.REFRIGERATE, ab_name: "Refrigerate", ty: PokemonType.ICE, ty_name: "ice" }, +])("Abilities - $ab_name", ({ ab, ty, ty_name }) => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + game.override + .battleStyle("single") + .startingLevel(100) + .ability(ab) + .moveset([Moves.TACKLE, Moves.REVELATION_DANCE, Moves.FURY_SWIPES]) + .enemySpecies(Species.DUSCLOPS) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH) + .enemyLevel(100); + }); + + it(`should change Normal-type attacks to ${ty_name} type and boost their power`, async () => { + await game.classicMode.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + vi.spyOn(playerPokemon, "getMoveType"); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + vi.spyOn(enemyPokemon, "apply"); + + const move = allMoves[Moves.TACKLE]; + vi.spyOn(move, "calculateBattlePower"); + + game.move.select(Moves.TACKLE); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(playerPokemon.getMoveType).toHaveLastReturnedWith(ty); + expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.EFFECTIVE); + expect(move.calculateBattlePower).toHaveReturnedWith(48); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + }); + + // Galvanize specifically would like to check for volt absorb's activation + if (ab === Abilities.GALVANIZE) { + it("should cause Normal-type attacks to activate Volt Absorb", async () => { + game.override.enemyAbility(Abilities.VOLT_ABSORB); + + await game.classicMode.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + vi.spyOn(playerPokemon, "getMoveType"); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + vi.spyOn(enemyPokemon, "apply"); + + enemyPokemon.hp = Math.floor(enemyPokemon.getMaxHp() * 0.8); + + game.move.select(Moves.TACKLE); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(playerPokemon.getMoveType).toHaveLastReturnedWith(PokemonType.ELECTRIC); + expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.NO_EFFECT); + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + }); + } + + it.each([ + { moveName: "Revelation Dance", move: Moves.REVELATION_DANCE, expected_ty: PokemonType.WATER }, + { moveName: "Judgement", move: Moves.JUDGMENT, expected_ty: PokemonType.NORMAL }, + { moveName: "Terrain Pulse", move: Moves.TERRAIN_PULSE, expected_ty: PokemonType.NORMAL }, + { moveName: "Weather Ball", move: Moves.WEATHER_BALL, expected_ty: PokemonType.NORMAL }, + { moveName: "Multi Attack", move: Moves.MULTI_ATTACK, expected_ty: PokemonType.NORMAL }, + ])("should not change the type of $moveName", async ({ move, expected_ty }) => { + game.override + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .moveset([move]) + .starterSpecies(Species.MAGIKARP); + + await game.classicMode.startBattle([Species.MAGIKARP]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const ty_spy = vi.spyOn(playerPokemon, "getMoveType"); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const enemy_spy = vi.spyOn(enemyPokemon, "apply"); + + game.move.select(move); + await game.phaseInterceptor.to("BerryPhase", false); + + expect(playerPokemon.getMoveType).toHaveLastReturnedWith(expected_ty); + + ty_spy.mockRestore(); + enemy_spy.mockRestore(); + }); + + it("should affect all hits of a Normal-type multi-hit move", async () => { + await game.classicMode.startBattle(); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const tySpy = vi.spyOn(playerPokemon, "getMoveType"); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + const enemySpy = vi.spyOn(enemyPokemon, "apply"); + + game.move.select(Moves.FURY_SWIPES); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.move.forceHit(); + + await game.phaseInterceptor.to("MoveEffectPhase"); + expect(playerPokemon.turnData.hitCount).toBeGreaterThan(1); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + + while (playerPokemon.turnData.hitsLeft > 0) { + const enemyStartingHp = enemyPokemon.hp; + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(playerPokemon.getMoveType).toHaveLastReturnedWith(ty); + expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); + } + tySpy.mockRestore(); + enemySpy.mockRestore(); + }); +}); diff --git a/test/abilities/galvanize.test.ts b/test/abilities/galvanize.test.ts deleted file mode 100644 index 5db8b642197..00000000000 --- a/test/abilities/galvanize.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/moves/move"; -import { PokemonType } from "#enums/pokemon-type"; -import { Abilities } from "#app/enums/abilities"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import GameManager from "#test/testUtils/gameManager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - -describe("Abilities - Galvanize", () => { - let phaserGame: Phaser.Game; - let game: GameManager; - - beforeAll(() => { - phaserGame = new Phaser.Game({ - type: Phaser.HEADLESS, - }); - }); - - afterEach(() => { - game.phaseInterceptor.restoreOg(); - }); - - beforeEach(() => { - game = new GameManager(phaserGame); - - game.override - .battleStyle("single") - .startingLevel(100) - .ability(Abilities.GALVANIZE) - .moveset([Moves.TACKLE, Moves.REVELATION_DANCE, Moves.FURY_SWIPES]) - .enemySpecies(Species.DUSCLOPS) - .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset(Moves.SPLASH) - .enemyLevel(100); - }); - - it("should change Normal-type attacks to Electric type and boost their power", async () => { - await game.classicMode.startBattle(); - - const playerPokemon = game.scene.getPlayerPokemon()!; - vi.spyOn(playerPokemon, "getMoveType"); - - const enemyPokemon = game.scene.getEnemyPokemon()!; - const spy = vi.spyOn(enemyPokemon, "getMoveEffectiveness"); - - const move = allMoves[Moves.TACKLE]; - vi.spyOn(move, "calculateBattlePower"); - - game.move.select(Moves.TACKLE); - - await game.phaseInterceptor.to("BerryPhase", false); - - expect(playerPokemon.getMoveType).toHaveLastReturnedWith(PokemonType.ELECTRIC); - expect(spy).toHaveReturnedWith(1); - expect(move.calculateBattlePower).toHaveReturnedWith(48); - expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - - spy.mockRestore(); - }); - - it("should cause Normal-type attacks to activate Volt Absorb", async () => { - game.override.enemyAbility(Abilities.VOLT_ABSORB); - - await game.classicMode.startBattle(); - - const playerPokemon = game.scene.getPlayerPokemon()!; - vi.spyOn(playerPokemon, "getMoveType"); - - const enemyPokemon = game.scene.getEnemyPokemon()!; - const spy = vi.spyOn(enemyPokemon, "getMoveEffectiveness"); - - enemyPokemon.hp = Math.floor(enemyPokemon.getMaxHp() * 0.8); - - game.move.select(Moves.TACKLE); - - await game.phaseInterceptor.to("BerryPhase", false); - - expect(playerPokemon.getMoveType).toHaveLastReturnedWith(PokemonType.ELECTRIC); - expect(spy).toHaveReturnedWith(0); - expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }); - - it("should not change the type of variable-type moves", async () => { - game.override.enemySpecies(Species.MIGHTYENA); - - await game.classicMode.startBattle([Species.ESPEON]); - - const playerPokemon = game.scene.getPlayerPokemon()!; - vi.spyOn(playerPokemon, "getMoveType"); - - const enemyPokemon = game.scene.getEnemyPokemon()!; - const spy = vi.spyOn(enemyPokemon, "getMoveEffectiveness"); - - game.move.select(Moves.REVELATION_DANCE); - await game.phaseInterceptor.to("BerryPhase", false); - - expect(playerPokemon.getMoveType).not.toHaveLastReturnedWith(PokemonType.ELECTRIC); - expect(spy).toHaveReturnedWith(0); - expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - }); - - it("should affect all hits of a Normal-type multi-hit move", async () => { - await game.classicMode.startBattle(); - - const playerPokemon = game.scene.getPlayerPokemon()!; - vi.spyOn(playerPokemon, "getMoveType"); - - const enemyPokemon = game.scene.getEnemyPokemon()!; - const spy = vi.spyOn(enemyPokemon, "getMoveEffectiveness"); - - game.move.select(Moves.FURY_SWIPES); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - await game.move.forceHit(); - - await game.phaseInterceptor.to("MoveEffectPhase"); - expect(playerPokemon.turnData.hitCount).toBeGreaterThan(1); - expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); - - while (playerPokemon.turnData.hitsLeft > 0) { - const enemyStartingHp = enemyPokemon.hp; - await game.phaseInterceptor.to("MoveEffectPhase"); - - expect(playerPokemon.getMoveType).toHaveLastReturnedWith(PokemonType.ELECTRIC); - expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); - } - - expect(spy).not.toHaveReturnedWith(0); - }); -}); diff --git a/test/moves/tera_blast.test.ts b/test/moves/tera_blast.test.ts index 8817f12b8cf..3fab0b22449 100644 --- a/test/moves/tera_blast.test.ts +++ b/test/moves/tera_blast.test.ts @@ -75,7 +75,7 @@ describe("Moves - Tera Blast", () => { await game.phaseInterceptor.to("MoveEffectPhase"); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100); - }, 20000); + }); it("is super effective against terastallized targets if user is Stellar tera type", async () => { await game.classicMode.startBattle(); @@ -189,5 +189,17 @@ describe("Moves - Tera Blast", () => { expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-1); - }, 20000); + }); + + it.each([ + { ab: "galvanize", ty: "electric", ab_id: Abilities.GALVANIZE, ty_id: PokemonType.ELECTRIC }, + { ab: "refrigerate", ty: "ice", ab_id: Abilities.REFRIGERATE, ty_id: PokemonType.ICE }, + { ab: "pixilate", ty: "fairy", ab_id: Abilities.PIXILATE, ty_id: PokemonType.FAIRY }, + { ab: "aerilate", ty: "flying", ab_id: Abilities.AERILATE, ty_id: PokemonType.FLYING }, + ])("should be $1 type if the user has $2", async ({ ab_id, ty_id }) => { + game.override.ability(ab_id).moveset([Moves.TERA_BLAST]).enemyAbility(Abilities.BALL_FETCH); + await game.classicMode.startBattle([Species.MAGIKARP]); + const playerPokemon = game.scene.getPlayerPokemon()!; + expect(playerPokemon.getMoveType(allMoves[Moves.TERA_BLAST])).toBe(ty_id); + }); });