From b75fa62c0d4203a23f91e504365cac81f869de4f Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Tue, 18 Feb 2025 20:38:40 -0600 Subject: [PATCH] Even more renames --- src/battle-scene.ts | 14 ++++++++ src/ui/starter-select-ui-handler.ts | 9 +++++ test/abilities/unseen_fist.test.ts | 35 +++++++------------ test/achievements/achievement.test.ts | 22 ++++++++++-- test/battle/battle.test.ts | 2 +- test/eggs/egg.test.ts | 2 +- test/eggs/manaphy-egg.test.ts | 2 +- test/phases/phases.test.ts | 6 ++-- test/ui/pokedex.test.ts | 18 +++++----- test/ui/starter-select.test.ts | 18 +++++----- test/utils/gameManager.ts | 31 ++++++++++++++-- test/utils/inputsHandler.ts | 2 +- .../mocks/mocksContainer/mockRectangle.ts | 3 ++ 13 files changed, 112 insertions(+), 52 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index e6649d0999a..7801cea2a36 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2375,6 +2375,20 @@ export default class BattleScene extends SceneBase { this.phaseQueue.splice(0, this.phaseQueue.length); } + /** + * Clears all phase-related stuff, including all phase queues, the current and standby phases, and a splice index. + * + * Currently, this is a utility function only used by unit tests. + */ + clearAllPhases(): void { + for (const queue of [ this.phaseQueue, this.phaseQueuePrepend, this.conditionalQueue, this.nextCommandPhaseQueue ]) { + queue.splice(0, queue.length); + } + this.currentPhase = null; + this.standbyPhase = null; + this.clearPhaseQueueSplice(); + } + /** * Used by function unshiftPhase(), sets index to start inserting at current length instead of the end of the array, useful if phaseQueuePrepend gets longer with Phases */ diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index b919679be00..9893f4ce998 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -3848,4 +3848,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler { icon.setFrame(species.getIconId(female, formIndex, false, variant)); } } + + /** + * Clears this UI's starter preferences. + * + * This is intended to only be used for unit tests that work with this UI. + */ + clearStarterPreferences() { + this.starterPreferences = {}; + } } diff --git a/test/abilities/unseen_fist.test.ts b/test/abilities/unseen_fist.test.ts index 584f997aa55..44c9fcd892b 100644 --- a/test/abilities/unseen_fist.test.ts +++ b/test/abilities/unseen_fist.test.ts @@ -33,33 +33,22 @@ describe("Abilities - Unseen Fist", () => { game.override.enemyLevel(100); }); - it( - "should cause a contact move to ignore Protect", - () => testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, true), - ); + it("should cause a contact move to ignore Protect", async () => + await testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, true)); - it( - "should not cause a non-contact move to ignore Protect", - () => testUnseenFistHitResult(game, Moves.ABSORB, Moves.PROTECT, false), - ); + it("should not cause a non-contact move to ignore Protect", async () => + await testUnseenFistHitResult(game, Moves.ABSORB, Moves.PROTECT, false)); - it( - "should not apply if the source has Long Reach", - async () => { - game.override.passiveAbility(Abilities.LONG_REACH); - await testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, false); - } - ); + it("should not apply if the source has Long Reach", async () => { + game.override.passiveAbility(Abilities.LONG_REACH); + await testUnseenFistHitResult(game, Moves.QUICK_ATTACK, Moves.PROTECT, false); + }); - it( - "should cause a contact move to ignore Wide Guard", - () => testUnseenFistHitResult(game, Moves.BREAKING_SWIPE, Moves.WIDE_GUARD, true), - ); + it("should cause a contact move to ignore Wide Guard", async () => + await testUnseenFistHitResult(game, Moves.BREAKING_SWIPE, Moves.WIDE_GUARD, true)); - it( - "should not cause a non-contact move to ignore Wide Guard", - () => testUnseenFistHitResult(game, Moves.BULLDOZE, Moves.WIDE_GUARD, false), - ); + it("should not cause a non-contact move to ignore Wide Guard", async () => + await testUnseenFistHitResult(game, Moves.BULLDOZE, Moves.WIDE_GUARD, false)); it( "should cause a contact move to ignore Protect, but not Substitute", diff --git a/test/achievements/achievement.test.ts b/test/achievements/achievement.test.ts index 0ddbebf0f6b..f58ddab6a87 100644 --- a/test/achievements/achievement.test.ts +++ b/test/achievements/achievement.test.ts @@ -4,7 +4,7 @@ import { NumberHolder } from "#app/utils"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import BattleScene from "#app/battle-scene"; +import type BattleScene from "#app/battle-scene"; describe("check some Achievement related stuff", () => { it ("should check Achievement creation", () => { @@ -68,6 +68,25 @@ describe("Achv", () => { }); describe("MoneyAchv", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + let scene: BattleScene; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + scene = game.scene; + }); + it("should create an instance of MoneyAchv", () => { const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); expect(moneyAchv).toBeInstanceOf(MoneyAchv); @@ -76,7 +95,6 @@ describe("MoneyAchv", () => { it("should validate the achievement based on the money amount", () => { const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); - const scene = new BattleScene(); scene.money = 5000; expect(moneyAchv.validate([])).toBe(false); diff --git a/test/battle/battle.test.ts b/test/battle/battle.test.ts index 8d6f7e0e904..d5c2ca02d87 100644 --- a/test/battle/battle.test.ts +++ b/test/battle/battle.test.ts @@ -122,7 +122,7 @@ describe("Test Battle Phase", () => { }, 20000); it("load 100% data file", async () => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; diff --git a/test/eggs/egg.test.ts b/test/eggs/egg.test.ts index d7ed07dd151..68e11f0aed7 100644 --- a/test/eggs/egg.test.ts +++ b/test/eggs/egg.test.ts @@ -29,7 +29,7 @@ describe("Egg Generation Tests", () => { }); beforeEach(async () => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); }); it("should return Kyogre for the 10th of June", () => { diff --git a/test/eggs/manaphy-egg.test.ts b/test/eggs/manaphy-egg.test.ts index 5bb5b790201..9dc155691ba 100644 --- a/test/eggs/manaphy-egg.test.ts +++ b/test/eggs/manaphy-egg.test.ts @@ -25,7 +25,7 @@ describe("Manaphy Eggs", () => { }); beforeEach(async () => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); /** * In our tests, we will perform an "RNG sweep" by letting rngSweepProgress diff --git a/test/phases/phases.test.ts b/test/phases/phases.test.ts index 36a405b8d15..39db1a75e45 100644 --- a/test/phases/phases.test.ts +++ b/test/phases/phases.test.ts @@ -31,7 +31,7 @@ describe("Phases", () => { it("should start the login phase", async () => { const loginPhase = new LoginPhase(); scene.unshiftPhase(loginPhase); - await game.phaseInterceptor.run(LoginPhase); + await game.phaseInterceptor.to(LoginPhase); expect(scene.ui.getMode()).to.equal(Mode.MESSAGE); }); }); @@ -40,7 +40,7 @@ describe("Phases", () => { it("should start the title phase", async () => { const titlePhase = new TitlePhase(); scene.unshiftPhase(titlePhase); - await game.phaseInterceptor.run(TitlePhase); + await game.phaseInterceptor.to(TitlePhase); expect(scene.ui.getMode()).to.equal(Mode.TITLE); }); }); @@ -49,7 +49,7 @@ describe("Phases", () => { it("should start the unavailable phase", async () => { const unavailablePhase = new UnavailablePhase(); scene.unshiftPhase(unavailablePhase); - await game.phaseInterceptor.run(UnavailablePhase); + await game.phaseInterceptor.to(UnavailablePhase); expect(scene.ui.getMode()).to.equal(Mode.UNAVAILABLE); }, 20000); }); diff --git a/test/ui/pokedex.test.ts b/test/ui/pokedex.test.ts index 458c171687b..ee3ea1be251 100644 --- a/test/ui/pokedex.test.ts +++ b/test/ui/pokedex.test.ts @@ -38,7 +38,7 @@ describe("UI - Pokedex", () => { }); it("Bulbasaur - shiny - variant 2 male", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -98,7 +98,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female hardy overgrow", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -160,7 +160,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -225,7 +225,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -286,7 +286,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - not shiny", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -346,7 +346,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - shiny - variant 1", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -408,7 +408,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Bulbasaur - shiny - variant 0", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -469,7 +469,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -533,7 +533,7 @@ describe("UI - Pokedex", () => { }, 20000); it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; diff --git a/test/ui/starter-select.test.ts b/test/ui/starter-select.test.ts index 15b5f643539..932f7a7cf3f 100644 --- a/test/ui/starter-select.test.ts +++ b/test/ui/starter-select.test.ts @@ -38,7 +38,7 @@ describe("UI - Starter select", () => { }); it("Bulbasaur - shiny - variant 2 male", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -98,7 +98,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female hardy overgrow", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -160,7 +160,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -225,7 +225,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - shiny - variant 2 female", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -286,7 +286,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - not shiny", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -346,7 +346,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - shiny - variant 1", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -408,7 +408,7 @@ describe("UI - Starter select", () => { }, 20000); it("Bulbasaur - shiny - variant 0", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -469,7 +469,7 @@ describe("UI - Starter select", () => { }, 20000); it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; @@ -533,7 +533,7 @@ describe("UI - Starter select", () => { }, 20000); it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async() => { - await game.importData("src/test/utils/saves/everything.prsv"); + await game.importData("test/utils/saves/everything.prsv"); const caughtCount = Object.keys(game.scene.gameData.dexData).filter((key) => { const species = game.scene.gameData.dexData[key]; return species.caughtAttr !== 0n; diff --git a/test/utils/gameManager.ts b/test/utils/gameManager.ts index 346464f0139..f1b619cd606 100644 --- a/test/utils/gameManager.ts +++ b/test/utils/gameManager.ts @@ -55,6 +55,9 @@ import TextInterceptor from "#test/utils/TextInterceptor"; import { AES, enc } from "crypto-js"; import fs from "fs"; import { expect, vi } from "vitest"; +import { globalScene } from "#app/global-scene"; +import type StarterSelectUiHandler from "#app/ui/starter-select-ui-handler"; +import { GameData } from "#app/system/game-data"; /** * Class to manage the game state and transitions between phases. @@ -84,10 +87,34 @@ export default class GameManager { ErrorInterceptor.getInstance().clear(); BattleScene.prototype.randBattleSeedInt = (range, min: number = 0) => min + range - 1; // This simulates a max roll this.gameWrapper = new GameWrapper(phaserGame, bypassLogin); - this.scene = new BattleScene(); + + let firstTimeScene = false; + if (globalScene) { + this.scene = globalScene; + } else { + this.scene = new BattleScene(); + this.gameWrapper.setScene(this.scene); + firstTimeScene = true; + } + this.phaseInterceptor = new PhaseInterceptor(this.scene); + + if (!firstTimeScene) { + this.scene.reset(); + (this.scene.ui.handlers[Mode.STARTER_SELECT] as StarterSelectUiHandler).clearStarterPreferences(); + this.scene.gameData = new GameData(); + this.scene.clearAllPhases(); + + // This part, in particular, must not be run before the PhaseInterceptor has been initialized. + this.scene.pushPhase(new LoginPhase()); + this.scene.pushPhase(new TitlePhase()); + this.scene.shiftPhase(); + + this.gameWrapper.scene = this.scene; + + (this.scene.ui.handlers[Mode.STARTER_SELECT] as StarterSelectUiHandler).clearStarterPreferences(); + } this.textInterceptor = new TextInterceptor(this.scene); - this.gameWrapper.setScene(this.scene); this.override = new OverridesHelper(this); this.move = new MoveHelper(this); this.classicMode = new ClassicModeHelper(this); diff --git a/test/utils/inputsHandler.ts b/test/utils/inputsHandler.ts index e2591def447..c2d37913db6 100644 --- a/test/utils/inputsHandler.ts +++ b/test/utils/inputsHandler.ts @@ -90,7 +90,7 @@ class Fakepad extends Phaser.Input.Gamepad.Gamepad { class FakeMobile { constructor() { - const fakeMobilePage = fs.readFileSync("./src/test/utils/fakeMobile.html", { encoding: "utf8", flag: "r" }); + const fakeMobilePage = fs.readFileSync("./test/utils/fakeMobile.html", { encoding: "utf8", flag: "r" }); const dom = new JSDOM(fakeMobilePage); Object.defineProperty(window, "document", { value: dom.window.document, diff --git a/test/utils/mocks/mocksContainer/mockRectangle.ts b/test/utils/mocks/mocksContainer/mockRectangle.ts index e4bca76b8fc..81c71df965f 100644 --- a/test/utils/mocks/mocksContainer/mockRectangle.ts +++ b/test/utils/mocks/mocksContainer/mockRectangle.ts @@ -77,4 +77,7 @@ export default class MockRectangle implements MockGameObject { setScale(scale) { // return this.phaserText.setScale(scale); } + + // Prevents a Phaser framework crash from `off` being undefined + off() {} }