diff --git a/src/test/abilities/infiltrator.test.ts b/src/test/abilities/infiltrator.test.ts index 01c5cef7796..8ea72b55b0c 100644 --- a/src/test/abilities/infiltrator.test.ts +++ b/src/test/abilities/infiltrator.test.ts @@ -75,7 +75,7 @@ describe("Abilities - Infiltrator", () => { }); // TODO: fix this interaction to pass this test - it.skip("should bypass the target's Mist", async () => { + it.todo("should bypass the target's Mist", async () => { await game.classicMode.startBattle([ Species.MAGIKARP ]); const player = game.scene.getPlayerPokemon()!; diff --git a/src/test/abilities/libero.test.ts b/src/test/abilities/libero.test.ts index e7bc9eeeb63..25d2309463e 100644 --- a/src/test/abilities/libero.test.ts +++ b/src/test/abilities/libero.test.ts @@ -54,6 +54,7 @@ describe("Abilities - Libero", () => { }, ); + // Test for Gen9+ functionality, we are using previous funcionality test.skip( "ability applies only once per switch in", async () => { diff --git a/src/test/abilities/protean.test.ts b/src/test/abilities/protean.test.ts index 0d7202e3f6d..368701610e4 100644 --- a/src/test/abilities/protean.test.ts +++ b/src/test/abilities/protean.test.ts @@ -54,6 +54,7 @@ describe("Abilities - Protean", () => { }, ); + // Test for Gen9+ functionality, we are using previous funcionality test.skip( "ability applies only once per switch in", async () => { diff --git a/src/test/battle/error-handling.test.ts b/src/test/battle/error-handling.test.ts deleted file mode 100644 index 208463e7064..00000000000 --- a/src/test/battle/error-handling.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -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("Error Handling", () => { - let phaserGame: Phaser.Game; - let game: GameManager; - const moveToUse = Moves.SPLASH; - - beforeAll(() => { - phaserGame = new Phaser.Game({ - type: Phaser.HEADLESS, - }); - }); - - afterEach(() => { - game.phaseInterceptor.restoreOg(); - }); - - beforeEach(() => { - game = new GameManager(phaserGame); - game.override - .battleType("single") - .startingWave(3); - game.override.starterSpecies(Species.MEWTWO); - game.override.enemySpecies(Species.RATTATA); - game.override.enemyAbility(Abilities.HYDRATION); - game.override.ability(Abilities.ZEN_MODE); - game.override.startingLevel(2000); - game.override.moveset([ moveToUse ]); - game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); - }); - - it.skip("to next turn", async () => { - await game.startBattle(); - const turn = game.scene.currentBattle.turn; - game.move.select(moveToUse); - await game.toNextTurn(); - expect(game.scene.currentBattle.turn).toBeGreaterThan(turn); - }, 20000); -}); - diff --git a/src/test/battlerTags/substitute.test.ts b/src/test/battlerTags/substitute.test.ts index 9922255abd2..6d1c6e0cda6 100644 --- a/src/test/battlerTags/substitute.test.ts +++ b/src/test/battlerTags/substitute.test.ts @@ -171,8 +171,8 @@ describe("BattlerTag - SubstituteTag", () => { } ); - /** TODO: Figure out how to mock a MoveEffectPhase correctly for this test */ - it.skip( + // TODO: Figure out how to mock a MoveEffectPhase correctly for this test + it.todo( "HIT lapse triggers on-hit message", async () => { const subject = new SubstituteTag(Moves.SUBSTITUTE, mockPokemon.id); diff --git a/src/test/moves/burning_jealousy.test.ts b/src/test/moves/burning_jealousy.test.ts index fe2735cfa96..abe2c09bb72 100644 --- a/src/test/moves/burning_jealousy.test.ts +++ b/src/test/moves/burning_jealousy.test.ts @@ -82,7 +82,8 @@ describe("Moves - Burning Jealousy", () => { expect(enemy.status?.effect).toBeUndefined(); }); - it.skip("should ignore weakness policy", async () => { // TODO: Make this test if WP is implemented + // TODO: Make this test if WP is implemented + it.todo("should ignore weakness policy", async () => { await game.classicMode.startBattle(); }); diff --git a/src/test/moves/parting_shot.test.ts b/src/test/moves/parting_shot.test.ts index cfdf6c15966..30ad3660a32 100644 --- a/src/test/moves/parting_shot.test.ts +++ b/src/test/moves/parting_shot.test.ts @@ -75,7 +75,7 @@ describe("Moves - Parting Shot", () => { } ); - it.skip( // TODO: fix this bug to pass the test! + it.todo( // TODO: fix this bug to pass the test! "Parting shot should fail if target is -6/-6 de-buffed", async () => { game.override.moveset([ Moves.PARTING_SHOT, Moves.MEMENTO, Moves.SPLASH ]); @@ -117,7 +117,7 @@ describe("Moves - Parting Shot", () => { } ); - it.skip( // TODO: fix this bug to pass the test! + it.todo( // TODO: fix this bug to pass the test! "Parting shot shouldn't allow switch out when mist is active", async () => { game.override @@ -138,7 +138,7 @@ describe("Moves - Parting Shot", () => { } ); - it.skip( // TODO: fix this bug to pass the test! + it.todo( // TODO: fix this bug to pass the test! "Parting shot shouldn't allow switch out against clear body ability", async () => { game.override @@ -158,7 +158,7 @@ describe("Moves - Parting Shot", () => { } ); - it.skip( // TODO: fix this bug to pass the test! + it.todo( // TODO: fix this bug to pass the test! "Parting shot should de-buff and not fail if no party available to switch - party size 1", async () => { await game.startBattle([ Species.MURKROW ]); @@ -175,7 +175,7 @@ describe("Moves - Parting Shot", () => { } ); - it.skip( // TODO: fix this bug to pass the test! + it.todo( // TODO: fix this bug to pass the test! "Parting shot regularly not fail if no party available to switch - party fainted", async () => { await game.startBattle([ Species.MURKROW, Species.MEOWTH ]); diff --git a/src/test/moves/tera_blast.test.ts b/src/test/moves/tera_blast.test.ts index 311ac0f0d0e..44dc29f68b5 100644 --- a/src/test/moves/tera_blast.test.ts +++ b/src/test/moves/tera_blast.test.ts @@ -87,7 +87,7 @@ describe("Moves - Tera Blast", () => { }); // Currently abilities are bugged and can't see when a move's category is changed - it.skip("uses the higher stat of the user's Atk and SpAtk for damage calculation", async () => { + it.todo("uses the higher stat of the user's Atk and SpAtk for damage calculation", async () => { game.override.enemyAbility(Abilities.TOXIC_DEBRIS); await game.startBattle(); diff --git a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index 2dcb165deca..d31583eac23 100644 --- a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -247,8 +247,7 @@ describe("Clowning Around - Mystery Encounter", () => { }); }); - // this is the test that's broken due to the event - it.skip("should randomize held items of the Pokemon with the most items, and not the held items of other pokemon", async () => { + it("should randomize held items of the Pokemon with the most items, and not the held items of other pokemon", async () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); // Set some moves on party for attack type booster generation diff --git a/src/test/phases/select-modifier-phase.test.ts b/src/test/phases/select-modifier-phase.test.ts index 6f1451df9f9..d4341a89b8c 100644 --- a/src/test/phases/select-modifier-phase.test.ts +++ b/src/test/phases/select-modifier-phase.test.ts @@ -1,20 +1,22 @@ -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import Phaser from "phaser"; -import GameManager from "#app/test/utils/gameManager"; -import { initSceneWithoutEncounterPhase } from "#app/test/utils/gameManagerUtils"; -import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import { ModifierTier } from "#app/modifier/modifier-tier"; -import * as Utils from "#app/utils"; -import { CustomModifierSettings, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; -import BattleScene from "#app/battle-scene"; -import { Species } from "#enums/species"; -import { Mode } from "#app/ui/ui"; -import { PlayerPokemon } from "#app/field/pokemon"; +import type BattleScene from "#app/battle-scene"; import { getPokemonSpecies } from "#app/data/pokemon-species"; +import { PlayerPokemon } from "#app/field/pokemon"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { CustomModifierSettings, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Mode } from "#app/ui/ui"; +import { shiftCharCodes } from "#app/utils"; +import { Abilities } from "#enums/abilities"; +import { Button } from "#enums/buttons"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -// TODO: why are the `expect(modifierSelectHandler.options.length).toEqual(#)` checks unreliable/failing? -describe.skip("SelectModifierPhase", () => { +describe("SelectModifierPhase", () => { let phaserGame: Phaser.Game; let game: GameManager; let scene: BattleScene; @@ -29,7 +31,11 @@ describe.skip("SelectModifierPhase", () => { game = new GameManager(phaserGame); scene = game.scene; - initSceneWithoutEncounterPhase(scene, [ Species.ABRA, Species.VOLCARONA ]); + game.override + .moveset([ Moves.FISSURE, Moves.SPLASH ]) + .ability(Abilities.NO_GUARD) + .startingLevel(200) + .enemySpecies(Species.MAGIKARP); }); afterEach(() => { @@ -39,6 +45,7 @@ describe.skip("SelectModifierPhase", () => { }); it("should start a select modifier phase", async () => { + initSceneWithoutEncounterPhase(scene, [ Species.ABRA, Species.VOLCARONA ]); const selectModifierPhase = new SelectModifierPhase(); scene.pushPhase(selectModifierPhase); await game.phaseInterceptor.run(SelectModifierPhase); @@ -47,10 +54,9 @@ describe.skip("SelectModifierPhase", () => { }); it("should generate random modifiers", async () => { - const selectModifierPhase = new SelectModifierPhase(); - scene.pushPhase(selectModifierPhase); - await game.phaseInterceptor.run(SelectModifierPhase); - + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + game.move.select(Moves.FISSURE); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; @@ -58,6 +64,7 @@ describe.skip("SelectModifierPhase", () => { }); it("should modify reroll cost", async () => { + initSceneWithoutEncounterPhase(scene, [ Species.ABRA, Species.VOLCARONA ]); const options = [ new ModifierTypeOption(modifierTypes.POTION(), 0, 100), new ModifierTypeOption(modifierTypes.ETHER(), 0, 400), @@ -72,50 +79,48 @@ describe.skip("SelectModifierPhase", () => { expect(cost2).toEqual(cost1 * 2); }); - it("should generate random modifiers from reroll", async () => { - let selectModifierPhase = new SelectModifierPhase(); - scene.pushPhase(selectModifierPhase); - await game.phaseInterceptor.run(SelectModifierPhase); + it.todo("should generate random modifiers from reroll", async () => { + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; + scene.shopCursorTarget = 0; + game.move.select(Moves.FISSURE); + await game.phaseInterceptor.to("SelectModifierPhase"); + + // TODO: nagivate the ui to reroll somehow + //const smphase = scene.getCurrentPhase() as SelectModifierPhase; expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; expect(modifierSelectHandler.options.length).toEqual(3); - // Simulate selecting reroll - selectModifierPhase = new SelectModifierPhase(1, [ ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.COMMON ]); - scene.unshiftPhase(selectModifierPhase); - scene.ui.setMode(Mode.MESSAGE).then(() => game.endPhase()); - await game.phaseInterceptor.run(SelectModifierPhase); + modifierSelectHandler.processInput(Button.ACTION); + expect(scene.money).toBe(1000000 - 250); expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); expect(modifierSelectHandler.options.length).toEqual(3); }); - it("should generate random modifiers of same tier for reroll with reroll lock", async () => { + it.todo("should generate random modifiers of same tier for reroll with reroll lock", async () => { + game.override.startingModifier([{ name: "LOCK_CAPSULE" }]); + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; // Just use fully random seed for this test vi.spyOn(scene, "resetSeed").mockImplementation(() => { - scene.waveSeed = Utils.shiftCharCodes(scene.seed, 5); + scene.waveSeed = shiftCharCodes(scene.seed, 5); Phaser.Math.RND.sow([ scene.waveSeed ]); console.log("Wave Seed:", scene.waveSeed, 5); scene.rngCounter = 0; }); - let selectModifierPhase = new SelectModifierPhase(); - scene.pushPhase(selectModifierPhase); - await game.phaseInterceptor.run(SelectModifierPhase); + game.move.select(Moves.FISSURE); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; expect(modifierSelectHandler.options.length).toEqual(3); const firstRollTiers: ModifierTier[] = modifierSelectHandler.options.map(o => o.modifierTypeOption.type.tier); - // Simulate selecting reroll with lock - scene.lockModifierTiers = true; - scene.reroll = true; - selectModifierPhase = new SelectModifierPhase(1, firstRollTiers); - scene.unshiftPhase(selectModifierPhase); - scene.ui.setMode(Mode.MESSAGE).then(() => game.endPhase()); - await game.phaseInterceptor.run(SelectModifierPhase); + // TODO: nagivate ui to reroll with lock capsule enabled expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); expect(modifierSelectHandler.options.length).toEqual(3); @@ -126,13 +131,15 @@ describe.skip("SelectModifierPhase", () => { }); it("should generate custom modifiers", async () => { + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; const customModifiers: CustomModifierSettings = { guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_ULTRA, modifierTypes.LEFTOVERS, modifierTypes.AMULET_COIN, modifierTypes.GOLDEN_PUNCH ] }; const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); - scene.pushPhase(selectModifierPhase); - await game.phaseInterceptor.run(SelectModifierPhase); - + scene.unshiftPhase(selectModifierPhase); + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; @@ -145,6 +152,8 @@ describe.skip("SelectModifierPhase", () => { }); it("should generate custom modifier tiers that can upgrade from luck", async () => { + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; const customModifiers: CustomModifierSettings = { guaranteedModifierTiers: [ ModifierTier.COMMON, ModifierTier.GREAT, ModifierTier.ULTRA, ModifierTier.ROGUE, ModifierTier.MASTER ] }; @@ -157,9 +166,9 @@ describe.skip("SelectModifierPhase", () => { scene.getPlayerParty().push(pokemon, pokemon, pokemon, pokemon, pokemon, pokemon); const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); - scene.pushPhase(selectModifierPhase); - await game.phaseInterceptor.run(SelectModifierPhase); - + scene.unshiftPhase(selectModifierPhase); + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; @@ -172,12 +181,15 @@ describe.skip("SelectModifierPhase", () => { }); it("should generate custom modifiers and modifier tiers together", async () => { + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; const customModifiers: CustomModifierSettings = { guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_COMMON ], guaranteedModifierTiers: [ ModifierTier.MASTER, ModifierTier.MASTER ] }; const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); - scene.pushPhase(selectModifierPhase); + scene.unshiftPhase(selectModifierPhase); + game.move.select(Moves.SPLASH); await game.phaseInterceptor.run(SelectModifierPhase); @@ -191,13 +203,16 @@ describe.skip("SelectModifierPhase", () => { }); it("should fill remaining modifiers if fillRemaining is true with custom modifiers", async () => { + await game.classicMode.startBattle([ Species.ABRA, Species.VOLCARONA ]); + scene.money = 1000000; const customModifiers: CustomModifierSettings = { guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM ], guaranteedModifierTiers: [ ModifierTier.MASTER ], fillRemaining: true }; const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); - scene.pushPhase(selectModifierPhase); + scene.unshiftPhase(selectModifierPhase); + game.move.select(Moves.SPLASH); await game.phaseInterceptor.run(SelectModifierPhase); diff --git a/src/test/utils/gameManagerUtils.ts b/src/test/utils/gameManagerUtils.ts index 828bdbc7b2a..af9f4bedc9a 100644 --- a/src/test/utils/gameManagerUtils.ts +++ b/src/test/utils/gameManagerUtils.ts @@ -1,13 +1,14 @@ -import BattleScene from "#app/battle-scene"; +import Battle, { BattleType } from "#app/battle"; +import type BattleScene from "#app/battle-scene"; import { getDailyRunStarters } from "#app/data/daily-run"; import { Gender } from "#app/data/gender"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; -import { Moves } from "#app/enums/moves"; import { PlayerPokemon } from "#app/field/pokemon"; import { GameModes, getGameMode } from "#app/game-mode"; +import type { StarterMoveset } from "#app/system/game-data"; import { Starter } from "#app/ui/starter-select-ui-handler"; +import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import Battle, { BattleType } from "#app/battle"; /** Function to convert Blob to string */ export function blobToString(blob) { @@ -31,7 +32,7 @@ export function holdOn(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } -export function generateStarter(scene, species?: Species[]) { +export function generateStarter(scene: BattleScene, species?: Species[]): Starter[] { const seed = "test"; const starters = getTestRunStarters(seed, species); const startingLevel = scene.gameMode.getStartingLevel(); @@ -42,12 +43,16 @@ export function generateStarter(scene, species?: Species[]) { ? !starterProps.female ? Gender.MALE : Gender.FEMALE : Gender.GENDERLESS; const starterPokemon = scene.addPlayerPokemon(starter.species, startingLevel, starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, undefined, starter.nature); - starter.moveset = starterPokemon.moveset; + const moveset: Moves[] = []; + starterPokemon.moveset.forEach((move) => { + moveset.push(move!.getMove().id); + }); + starter.moveset = moveset as StarterMoveset; } return starters; } -function getTestRunStarters(seed, species) { +function getTestRunStarters(seed: string, species?: Species[]): Starter[] { if (!species) { return getDailyRunStarters(seed); } @@ -71,7 +76,7 @@ function getTestRunStarters(seed, species) { return starters; } -export function waitUntil(truth) { +export function waitUntil(truth): Promise { return new Promise(resolve => { const interval = setInterval(() => { if (truth()) { @@ -83,7 +88,7 @@ export function waitUntil(truth) { } /** Get the index of `move` from the moveset of the pokemon on the player's field at location `pokemonIndex` */ -export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: Moves) { +export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: Moves): number { const playerPokemon = scene.getPlayerField()[pokemonIndex]; const moveSet = playerPokemon.getMoveset(); const index = moveSet.findIndex((m) => m?.moveId === move && m?.ppUsed < m?.getMovePp()); @@ -93,10 +98,8 @@ export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: M /** * Useful for populating party, wave index, etc. without having to spin up and run through an entire EncounterPhase - * @param scene - * @param species */ -export function initSceneWithoutEncounterPhase(scene: BattleScene, species?: Species[]) { +export function initSceneWithoutEncounterPhase(scene: BattleScene, species?: Species[]): void { const starters = generateStarter(scene, species); starters.forEach((starter) => { const starterProps = scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr); diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index 4029e5e168c..9f03f40ec97 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -510,7 +510,13 @@ export default class PhaseInterceptor { const currentHandler = this.scene.ui.getHandler(); if (expireFn) { this.prompts.shift(); - } else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget && currentHandler.active && (!actionForNextPrompt.awaitingActionInput || (actionForNextPrompt.awaitingActionInput && currentHandler.awaitingActionInput))) { + } else if ( + currentMode === actionForNextPrompt.mode + && currentPhase === actionForNextPrompt.phaseTarget + && currentHandler.active + && (!actionForNextPrompt.awaitingActionInput + || (actionForNextPrompt.awaitingActionInput && currentHandler.awaitingActionInput)) + ) { const prompt = this.prompts.shift(); if (prompt?.callback) { prompt.callback();