mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-09 17:09:26 +02:00
[Test] Address flaky tests and add Metronome mock helper (#6093)
- Fix `copycat`, `first-attack-double-power` and `ability-ignore-moves` * Add utility method for forcing metronome move * Stop bolt beak / fiscious rend flakiness
This commit is contained in:
parent
22e399be8b
commit
de8491505b
@ -2,10 +2,9 @@ import { AbilityId } from "#enums/ability-id";
|
|||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { RandomMoveAttr } from "#moves/move";
|
|
||||||
import { GameManager } from "#test/testUtils/gameManager";
|
import { GameManager } from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
describe("Moves - Ability-Ignoring Moves", () => {
|
describe("Moves - Ability-Ignoring Moves", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -55,10 +54,9 @@ describe("Moves - Ability-Ignoring Moves", () => {
|
|||||||
expect(enemy.isFainted()).toBe(true);
|
expect(enemy.isFainted()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: figure out why this test sometimes fails (cross-test game state pollution?)
|
it("should not ignore enemy abilities when called by Metronome", async () => {
|
||||||
it.todo("should not ignore enemy abilities when called by Metronome", async () => {
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MILOTIC]);
|
await game.classicMode.startBattle([SpeciesId.MILOTIC]);
|
||||||
vi.spyOn(RandomMoveAttr.prototype, "getMoveOverride").mockReturnValue(MoveId.PHOTON_GEYSER);
|
game.move.forceMetronomeMove(MoveId.PHOTON_GEYSER, true);
|
||||||
|
|
||||||
const enemy = game.field.getEnemyPokemon();
|
const enemy = game.field.getEnemyPokemon();
|
||||||
game.move.select(MoveId.METRONOME);
|
game.move.select(MoveId.METRONOME);
|
||||||
|
@ -5,10 +5,9 @@ import { MoveResult } from "#enums/move-result";
|
|||||||
import { MoveUseMode } from "#enums/move-use-mode";
|
import { MoveUseMode } from "#enums/move-use-mode";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { RandomMoveAttr } from "#moves/move";
|
|
||||||
import { GameManager } from "#test/testUtils/gameManager";
|
import { GameManager } from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
describe("Moves - Copycat", () => {
|
describe("Moves - Copycat", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -65,7 +64,7 @@ describe("Moves - Copycat", () => {
|
|||||||
it("should copy the called move when the last move successfully calls another", async () => {
|
it("should copy the called move when the last move successfully calls another", async () => {
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.METRONOME]).enemyMoveset(MoveId.COPYCAT);
|
game.override.moveset([MoveId.SPLASH, MoveId.METRONOME]).enemyMoveset(MoveId.COPYCAT);
|
||||||
await game.classicMode.startBattle([SpeciesId.DRAMPA]);
|
await game.classicMode.startBattle([SpeciesId.DRAMPA]);
|
||||||
vi.spyOn(RandomMoveAttr.prototype, "getMoveOverride").mockReturnValue(MoveId.SWORDS_DANCE);
|
game.move.forceMetronomeMove(MoveId.SWORDS_DANCE, true);
|
||||||
|
|
||||||
game.move.select(MoveId.METRONOME);
|
game.move.select(MoveId.METRONOME);
|
||||||
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); // Player moves first so enemy can copy Swords Dance
|
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); // Player moves first so enemy can copy Swords Dance
|
||||||
|
@ -7,12 +7,11 @@ import { MoveUseMode } from "#enums/move-use-mode";
|
|||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { GameManager } from "#test/testUtils/gameManager";
|
import { GameManager } from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, type MockInstance, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
describe("Moves - Fishious Rend & Bolt Beak", () => {
|
describe("Moves - Fishious Rend & Bolt Beak", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
let game: GameManager;
|
let game: GameManager;
|
||||||
let powerSpy: MockInstance;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
phaserGame = new Phaser.Game({
|
phaserGame = new Phaser.Game({
|
||||||
@ -35,15 +34,13 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
.enemySpecies(SpeciesId.DRACOVISH)
|
.enemySpecies(SpeciesId.DRACOVISH)
|
||||||
.enemyAbility(AbilityId.BALL_FETCH)
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
.enemyMoveset(MoveId.SPLASH);
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
|
|
||||||
powerSpy = vi.spyOn(allMoves[MoveId.BOLT_BEAK], "calculateBattlePower");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each<{ name: string; move: MoveId }>([
|
it.each<{ name: string; move: MoveId }>([
|
||||||
{ name: "Bolt Beak", move: MoveId.BOLT_BEAK },
|
{ name: "Bolt Beak", move: MoveId.BOLT_BEAK },
|
||||||
{ name: "Fishious Rend", move: MoveId.FISHIOUS_REND },
|
{ name: "Fishious Rend", move: MoveId.FISHIOUS_REND },
|
||||||
])("$name should double power if the user moves before the target", async ({ move }) => {
|
])("$name should double power if the user moves before the target", async ({ move }) => {
|
||||||
powerSpy = vi.spyOn(allMoves[move], "calculateBattlePower");
|
const powerSpy = vi.spyOn(allMoves[move], "calculateBattlePower");
|
||||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
// turn 1: enemy, then player (no boost)
|
// turn 1: enemy, then player (no boost)
|
||||||
@ -63,6 +60,7 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
|
|
||||||
it("should only consider the selected target in Double Battles", async () => {
|
it("should only consider the selected target in Double Battles", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
|
const powerSpy = vi.spyOn(allMoves[MoveId.BOLT_BEAK], "calculateBattlePower");
|
||||||
await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.MILOTIC]);
|
await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.MILOTIC]);
|
||||||
|
|
||||||
// Use move after everyone but P1 and enemy 1 have already moved
|
// Use move after everyone but P1 and enemy 1 have already moved
|
||||||
@ -76,6 +74,7 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
|
|
||||||
it("should double power on the turn the target switches in", async () => {
|
it("should double power on the turn the target switches in", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
const powerSpy = vi.spyOn(allMoves[MoveId.BOLT_BEAK], "calculateBattlePower");
|
||||||
|
|
||||||
game.move.use(MoveId.BOLT_BEAK);
|
game.move.use(MoveId.BOLT_BEAK);
|
||||||
game.forceEnemyToSwitch();
|
game.forceEnemyToSwitch();
|
||||||
@ -86,6 +85,7 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
|
|
||||||
it("should double power on forced switch-induced sendouts", async () => {
|
it("should double power on forced switch-induced sendouts", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
const powerSpy = vi.spyOn(allMoves[MoveId.BOLT_BEAK], "calculateBattlePower");
|
||||||
|
|
||||||
game.move.use(MoveId.BOLT_BEAK);
|
game.move.use(MoveId.BOLT_BEAK);
|
||||||
await game.move.forceEnemyMove(MoveId.U_TURN);
|
await game.move.forceEnemyMove(MoveId.U_TURN);
|
||||||
@ -100,7 +100,7 @@ describe("Moves - Fishious Rend & Bolt Beak", () => {
|
|||||||
{ type: "an Instructed", allyMove: MoveId.INSTRUCT },
|
{ type: "an Instructed", allyMove: MoveId.INSTRUCT },
|
||||||
])("should double power if $type move is used as the target's first action that turn", async ({ allyMove }) => {
|
])("should double power if $type move is used as the target's first action that turn", async ({ allyMove }) => {
|
||||||
game.override.battleStyle("double").enemyAbility(AbilityId.DANCER);
|
game.override.battleStyle("double").enemyAbility(AbilityId.DANCER);
|
||||||
powerSpy = vi.spyOn(allMoves[MoveId.FISHIOUS_REND], "calculateBattlePower");
|
const powerSpy = vi.spyOn(allMoves[MoveId.FISHIOUS_REND], "calculateBattlePower");
|
||||||
await game.classicMode.startBattle([SpeciesId.DRACOVISH, SpeciesId.ARCTOZOLT]);
|
await game.classicMode.startBattle([SpeciesId.DRACOVISH, SpeciesId.ARCTOZOLT]);
|
||||||
|
|
||||||
// Simulate enemy having used splash last turn to allow Instruct to copy it
|
// Simulate enemy having used splash last turn to allow Instruct to copy it
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
|
import { allMoves } from "#data/data-lists";
|
||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
@ -12,6 +13,7 @@ import type { EnemyCommandPhase } from "#phases/enemy-command-phase";
|
|||||||
import { MoveEffectPhase } from "#phases/move-effect-phase";
|
import { MoveEffectPhase } from "#phases/move-effect-phase";
|
||||||
import { GameManagerHelper } from "#test/testUtils/helpers/gameManagerHelper";
|
import { GameManagerHelper } from "#test/testUtils/helpers/gameManagerHelper";
|
||||||
import { coerceArray, toReadableString } from "#utils/common";
|
import { coerceArray, toReadableString } from "#utils/common";
|
||||||
|
import type { MockInstance } from "vitest";
|
||||||
import { expect, vi } from "vitest";
|
import { expect, vi } from "vitest";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -305,4 +307,20 @@ export class MoveHelper extends GameManagerHelper {
|
|||||||
*/
|
*/
|
||||||
await this.game.phaseInterceptor.to("EnemyCommandPhase");
|
await this.game.phaseInterceptor.to("EnemyCommandPhase");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force the move used by Metronome to be a specific move.
|
||||||
|
* @param move - The move to force metronome to use
|
||||||
|
* @param once - If `true`, uses {@linkcode MockInstance#mockReturnValueOnce} when mocking, else uses {@linkcode MockInstance#mockReturnValue}.
|
||||||
|
* @returns The spy that for Metronome that was mocked (Usually unneeded).
|
||||||
|
*/
|
||||||
|
public forceMetronomeMove(move: MoveId, once = false): MockInstance {
|
||||||
|
const spy = vi.spyOn(allMoves[MoveId.METRONOME].getAttrs("RandomMoveAttr")[0], "getMoveOverride");
|
||||||
|
if (once) {
|
||||||
|
spy.mockReturnValueOnce(move);
|
||||||
|
} else {
|
||||||
|
spy.mockReturnValue(move);
|
||||||
|
}
|
||||||
|
return spy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user