Test updating

This commit is contained in:
NightKev 2024-09-17 04:34:10 -07:00
parent d1f0bf8c2f
commit b400cbf0c1
5 changed files with 92 additions and 73 deletions

View File

@ -7,7 +7,6 @@ import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
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, vi } from "vitest";
import { BerryPhase } from "#app/phases/berry-phase.js";
describe("Moves - U-turn", () => { describe("Moves - U-turn", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -36,40 +35,28 @@ describe("Moves - U-turn", () => {
}); });
it("triggers regenerator a single time when a regenerator user switches out with u-turn", async () => { it("triggers regenerator a single time when a regenerator user switches out with u-turn", async () => {
// arrange
const playerHp = 1; const playerHp = 1;
game.override.ability(Abilities.REGENERATOR); game.override.ability(Abilities.REGENERATOR);
await game.startBattle([ await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]);
Species.RAICHU,
Species.SHUCKLE
]);
game.scene.getPlayerPokemon()!.hp = playerHp; game.scene.getPlayerPokemon()!.hp = playerHp;
// act
game.move.select(Moves.U_TURN); game.move.select(Moves.U_TURN);
game.doSelectPartyPokemon(1); game.doSelectPartyPokemon(1);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
// assert
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.SHUCKLE); expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.SHUCKLE);
expect(game.scene.getParty()[1].hp).toEqual(Math.floor(game.scene.getParty()[1].getMaxHp() * 0.33 + playerHp)); expect(game.scene.getParty()[1].hp).toEqual(Math.floor(game.scene.getParty()[1].getMaxHp() * 0.33 + playerHp));
expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase"); expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase");
}, 20000); }, 20000);
it("triggers rough skin on the u-turn user before a new pokemon is switched in", async () => { it("triggers rough skin on the u-turn user before a new pokemon is switched in", async () => {
// arrange
game.override.enemyAbility(Abilities.ROUGH_SKIN); game.override.enemyAbility(Abilities.ROUGH_SKIN);
await game.startBattle([ await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]);
Species.RAICHU,
Species.SHUCKLE
]);
// act
game.move.select(Moves.U_TURN); game.move.select(Moves.U_TURN);
game.doSelectPartyPokemon(1); game.doSelectPartyPokemon(1);
await game.phaseInterceptor.to(SwitchPhase, false); await game.phaseInterceptor.to(SwitchPhase, false);
// assert
const playerPkm = game.scene.getPlayerPokemon()!; const playerPkm = game.scene.getPlayerPokemon()!;
expect(playerPkm.species.speciesId).toEqual(Species.RAICHU); expect(playerPkm.species.speciesId).toEqual(Species.RAICHU);
expect(playerPkm.hp).not.toEqual(playerPkm.getMaxHp()); expect(playerPkm.hp).not.toEqual(playerPkm.getMaxHp());
@ -78,46 +65,17 @@ describe("Moves - U-turn", () => {
}, 20000); }, 20000);
it("triggers contact abilities on the u-turn user (eg poison point) before a new pokemon is switched in", async () => { it("triggers contact abilities on the u-turn user (eg poison point) before a new pokemon is switched in", async () => {
// arrange
game.override.enemyAbility(Abilities.POISON_POINT); game.override.enemyAbility(Abilities.POISON_POINT);
await game.startBattle([ await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]);
Species.RAICHU,
Species.SHUCKLE
]);
vi.spyOn(game.scene.getEnemyPokemon()!, "randSeedInt").mockReturnValue(0); vi.spyOn(game.scene.getEnemyPokemon()!, "randSeedInt").mockReturnValue(0);
// act
game.move.select(Moves.U_TURN); game.move.select(Moves.U_TURN);
await game.phaseInterceptor.to(SwitchPhase, false); await game.phaseInterceptor.to(SwitchPhase, false);
// assert
const playerPkm = game.scene.getPlayerPokemon()!; const playerPkm = game.scene.getPlayerPokemon()!;
expect(playerPkm.species.speciesId).toEqual(Species.RAICHU); expect(playerPkm.species.speciesId).toEqual(Species.RAICHU);
expect(playerPkm.status?.effect).toEqual(StatusEffect.POISON); expect(playerPkm.status?.effect).toEqual(StatusEffect.POISON);
expect(game.scene.getEnemyPokemon()!.battleData.abilityRevealed).toBe(true); // proxy for asserting ability activated expect(game.scene.getEnemyPokemon()!.battleData.abilityRevealed).toBe(true); // proxy for asserting ability activated
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase"); expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
}, 20000); }, 20000);
it("does not switch out the user if the move fails", async () => {
// arrange
game.override
.enemySpecies(Species.DUGTRIO)
.moveset(Moves.VOLT_SWITCH); // cheating a little here but no types are immune to bug
await game.startBattle([
Species.RAICHU,
Species.SHUCKLE
]);
// act
game.doAttack(getMovePosition(game.scene, 0, Moves.U_TURN));
game.onNextPrompt("SwitchPhase", Mode.PARTY, () => {
expect.fail("Switch was forced");
}, () => game.isCurrentPhase(BerryPhase));
await game.phaseInterceptor.to(BerryPhase, false);
// assert
const playerPkm = game.scene.getPlayerPokemon()!;
expect(playerPkm.species.speciesId).toEqual(Species.RAICHU);
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
}, 20000);
}); });

View File

@ -0,0 +1,50 @@
import { BerryPhase } from "#app/phases/berry-phase";
import { Mode } from "#app/ui/ui";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
describe("Moves - Volt Switch", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
const TIMEOUT = 20 * 1000;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([Moves.SPLASH])
.battleType("single")
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH);
});
it("does not switch out the user if the move fails", async () => {
game.override
.enemySpecies(Species.DUGTRIO)
.moveset(Moves.VOLT_SWITCH);
await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]);
game.move.select(Moves.VOLT_SWITCH);
game.onNextPrompt("SwitchPhase", Mode.PARTY, () => {
expect.fail("Switch was forced");
}, () => game.isCurrentPhase(BerryPhase));
await game.phaseInterceptor.to(BerryPhase, false);
const playerPkm = game.scene.getPlayerPokemon()!;
expect(playerPkm.species.speciesId).toEqual(Species.RAICHU);
expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase");
}, TIMEOUT);
});

View File

@ -1,20 +1,23 @@
import { updateUserInfo } from "#app/account"; import { updateUserInfo } from "#app/account";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattleStyle } from "#app/enums/battle-style";
import { Moves } from "#app/enums/moves";
import { getMoveTargets } from "#app/data/move"; import { getMoveTargets } from "#app/data/move";
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { BattleStyle } from "#app/enums/battle-style";
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
import { Moves } from "#app/enums/moves";
import Pokemon from "#app/field/pokemon";
import Trainer from "#app/field/trainer"; import Trainer from "#app/field/trainer";
import { GameModes, getGameMode } from "#app/game-mode"; import { GameModes, getGameMode } from "#app/game-mode";
import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type";
import overrides from "#app/overrides"; import overrides from "#app/overrides";
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
import { CommandPhase } from "#app/phases/command-phase"; import { CommandPhase } from "#app/phases/command-phase";
import { EncounterPhase } from "#app/phases/encounter-phase"; import { EncounterPhase } from "#app/phases/encounter-phase";
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
import { FaintPhase } from "#app/phases/faint-phase"; import { FaintPhase } from "#app/phases/faint-phase";
import { LoginPhase } from "#app/phases/login-phase"; import { LoginPhase } from "#app/phases/login-phase";
import { MovePhase } from "#app/phases/move-phase"; import { MovePhase } from "#app/phases/move-phase";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
import { NewBattlePhase } from "#app/phases/new-battle-phase"; import { NewBattlePhase } from "#app/phases/new-battle-phase";
import { SelectStarterPhase } from "#app/phases/select-starter-phase"; import { SelectStarterPhase } from "#app/phases/select-starter-phase";
import { SelectTargetPhase } from "#app/phases/select-target-phase"; import { SelectTargetPhase } from "#app/phases/select-target-phase";
@ -24,13 +27,16 @@ import { TurnInitPhase } from "#app/phases/turn-init-phase";
import { TurnStartPhase } from "#app/phases/turn-start-phase"; import { TurnStartPhase } from "#app/phases/turn-start-phase";
import ErrorInterceptor from "#app/test/utils/errorInterceptor"; import ErrorInterceptor from "#app/test/utils/errorInterceptor";
import InputsHandler from "#app/test/utils/inputsHandler"; import InputsHandler from "#app/test/utils/inputsHandler";
import BattleMessageUiHandler from "#app/ui/battle-message-ui-handler";
import CommandUiHandler from "#app/ui/command-ui-handler"; import CommandUiHandler from "#app/ui/command-ui-handler";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
import PartyUiHandler from "#app/ui/party-ui-handler"; import PartyUiHandler from "#app/ui/party-ui-handler";
import TargetSelectUiHandler from "#app/ui/target-select-ui-handler"; import TargetSelectUiHandler from "#app/ui/target-select-ui-handler";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import { isNullOrUndefined } from "#app/utils";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { ExpNotification } from "#enums/exp-notification"; import { ExpNotification } from "#enums/exp-notification";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { generateStarter, waitUntil } from "#test/utils/gameManagerUtils"; import { generateStarter, waitUntil } from "#test/utils/gameManagerUtils";
@ -39,21 +45,14 @@ import PhaseInterceptor from "#test/utils/phaseInterceptor";
import TextInterceptor from "#test/utils/TextInterceptor"; import TextInterceptor from "#test/utils/TextInterceptor";
import { AES, enc } from "crypto-js"; import { AES, enc } from "crypto-js";
import fs from "fs"; import fs from "fs";
import { vi } from "vitest"; import { expect, vi } from "vitest";
import { ChallengeModeHelper } from "./helpers/challengeModeHelper";
import { ClassicModeHelper } from "./helpers/classicModeHelper"; import { ClassicModeHelper } from "./helpers/classicModeHelper";
import { DailyModeHelper } from "./helpers/dailyModeHelper"; import { DailyModeHelper } from "./helpers/dailyModeHelper";
import { ChallengeModeHelper } from "./helpers/challengeModeHelper";
import { MoveHelper } from "./helpers/moveHelper"; import { MoveHelper } from "./helpers/moveHelper";
import { OverridesHelper } from "./helpers/overridesHelper"; import { OverridesHelper } from "./helpers/overridesHelper";
import { SettingsHelper } from "./helpers/settingsHelper";
import { ReloadHelper } from "./helpers/reloadHelper"; import { ReloadHelper } from "./helpers/reloadHelper";
import { CheckSwitchPhase } from "#app/phases/check-switch-phase"; import { SettingsHelper } from "./helpers/settingsHelper";
import BattleMessageUiHandler from "#app/ui/battle-message-ui-handler";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases";
import { expect } from "vitest";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { isNullOrUndefined } from "#app/utils";
import { ExpGainsSpeed } from "#app/enums/exp-gains-speed";
/** /**
* Class to manage the game state and transitions between phases. * Class to manage the game state and transitions between phases.

View File

@ -8,10 +8,10 @@ import * as GameMode from "#app/game-mode";
import { GameModes, getGameMode } from "#app/game-mode"; import { GameModes, getGameMode } from "#app/game-mode";
import { ModifierOverride } from "#app/modifier/modifier-type"; import { ModifierOverride } from "#app/modifier/modifier-type";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { vi } from "vitest"; import { vi } from "vitest";
import { GameManagerHelper } from "./gameManagerHelper"; import { GameManagerHelper } from "./gameManagerHelper";
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
/** /**
* Helper to handle overrides in tests * Helper to handle overrides in tests
@ -325,6 +325,17 @@ export class OverridesHelper extends GameManagerHelper {
return this; return this;
} }
/**
* Overrides the trainer AI's party
* @param species List of pokemon to generate in the party
* @returns this
*/
enemyParty(species: Species[]) {
vi.spyOn(Overrides, "TRAINER_PARTY_OVERRIDE", "get").mockReturnValue(species);
this.log("Enemy trainer party set to:", species);
return this;
}
/** /**
* Override the encounter chance for a mystery encounter. * Override the encounter chance for a mystery encounter.
* @param percentage the encounter chance in % * @param percentage the encounter chance in %

View File

@ -1,5 +1,4 @@
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
import { AttemptRunPhase } from "#app/phases/attempt-run-phase"; import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
import { BattleEndPhase } from "#app/phases/battle-end-phase"; import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { BerryPhase } from "#app/phases/berry-phase"; import { BerryPhase } from "#app/phases/berry-phase";
@ -11,17 +10,28 @@ import { EncounterPhase } from "#app/phases/encounter-phase";
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase"; import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
import { EvolutionPhase } from "#app/phases/evolution-phase"; import { EvolutionPhase } from "#app/phases/evolution-phase";
import { ExpPhase } from "#app/phases/exp-phase";
import { FaintPhase } from "#app/phases/faint-phase"; import { FaintPhase } from "#app/phases/faint-phase";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#app/phases/learn-move-phase";
import { LevelCapPhase } from "#app/phases/level-cap-phase"; import { LevelCapPhase } from "#app/phases/level-cap-phase";
import { LoginPhase } from "#app/phases/login-phase"; import { LoginPhase } from "#app/phases/login-phase";
import { MessagePhase } from "#app/phases/message-phase"; import { MessagePhase } from "#app/phases/message-phase";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase";
import { MovePhase } from "#app/phases/move-phase"; import { MovePhase } from "#app/phases/move-phase";
import {
MysteryEncounterBattlePhase,
MysteryEncounterOptionSelectedPhase,
MysteryEncounterPhase,
MysteryEncounterRewardsPhase,
PostMysteryEncounterPhase
} from "#app/phases/mystery-encounter-phases";
import { NewBattlePhase } from "#app/phases/new-battle-phase"; import { NewBattlePhase } from "#app/phases/new-battle-phase";
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase"; import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
import { PartyExpPhase } from "#app/phases/party-exp-phase";
import { PartyHealPhase } from "#app/phases/party-heal-phase";
import { PostSummonPhase } from "#app/phases/post-summon-phase"; import { PostSummonPhase } from "#app/phases/post-summon-phase";
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
import { SelectGenderPhase } from "#app/phases/select-gender-phase"; import { SelectGenderPhase } from "#app/phases/select-gender-phase";
@ -41,17 +51,9 @@ import { TurnInitPhase } from "#app/phases/turn-init-phase";
import { TurnStartPhase } from "#app/phases/turn-start-phase"; import { TurnStartPhase } from "#app/phases/turn-start-phase";
import { UnavailablePhase } from "#app/phases/unavailable-phase"; import { UnavailablePhase } from "#app/phases/unavailable-phase";
import { VictoryPhase } from "#app/phases/victory-phase"; import { VictoryPhase } from "#app/phases/victory-phase";
import { PartyHealPhase } from "#app/phases/party-heal-phase"; import ErrorInterceptor from "#app/test/utils/errorInterceptor";
import UI, { Mode } from "#app/ui/ui"; import UI, { Mode } from "#app/ui/ui";
import { import { expect } from "vitest";
MysteryEncounterBattlePhase,
MysteryEncounterOptionSelectedPhase,
MysteryEncounterPhase,
MysteryEncounterRewardsPhase,
PostMysteryEncounterPhase
} from "#app/phases/mystery-encounter-phases";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
import { PartyExpPhase } from "#app/phases/party-exp-phase";
type PhaseClassType = (abstract new (...args: any) => Phase); // `typeof Phase` does not work here because of some issue with ctor signatures type PhaseClassType = (abstract new (...args: any) => Phase); // `typeof Phase` does not work here because of some issue with ctor signatures
@ -62,7 +64,6 @@ export interface PromptHandler {
expireFn?: () => void; expireFn?: () => void;
awaitingActionInput?: boolean; awaitingActionInput?: boolean;
} }
import { ExpPhase } from "#app/phases/exp-phase";
export default class PhaseInterceptor { export default class PhaseInterceptor {
public scene; public scene;
@ -227,7 +228,7 @@ export default class PhaseInterceptor {
* @param skipFn - Optional skip function. * @param skipFn - Optional skip function.
* @returns A promise that resolves when the phase is run. * @returns A promise that resolves when the phase is run.
*/ */
run(phaseTarget, skipFn?): Promise<void> { async run(phaseTarget, skipFn?): Promise<void> {
const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name;
this.scene.moveAnimations = null; // Mandatory to avoid crash this.scene.moveAnimations = null; // Mandatory to avoid crash
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {