Create unified test file for galvanize, pixilate, and refrigerate

This commit is contained in:
Sirz Benjie 2025-04-15 12:14:46 -05:00
parent cd093c908a
commit dbda6e8d47
No known key found for this signature in database
GPG Key ID: 4A524B4D196C759E
3 changed files with 172 additions and 133 deletions

View File

@ -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();
});
});

View File

@ -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);
});
});

View File

@ -75,7 +75,7 @@ describe("Moves - Tera Blast", () => {
await game.phaseInterceptor.to("MoveEffectPhase"); await game.phaseInterceptor.to("MoveEffectPhase");
expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100);
}, 20000); });
it("is super effective against terastallized targets if user is Stellar tera type", async () => { it("is super effective against terastallized targets if user is Stellar tera type", async () => {
await game.classicMode.startBattle(); await game.classicMode.startBattle();
@ -189,5 +189,17 @@ describe("Moves - Tera Blast", () => {
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1);
expect(playerPokemon.getStatStage(Stat.ATK)).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);
});
}); });