From 8395b8fd27f94fbff9132866c8772f9afb4f206a Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Thu, 29 May 2025 10:45:06 -0400 Subject: [PATCH] Fixed tests --- test/abilities/magic_guard.test.ts | 103 +++++++----------- test/achievements/achievement.test.ts | 1 - test/battle/battle.test.ts | 27 ++--- test/moves/instruct.test.ts | 3 +- .../absolute-avarice-encounter.test.ts | 2 +- .../mystery-encounter-utils.test.ts | 21 +++- test/testUtils/helpers/moveHelper.ts | 4 +- 7 files changed, 74 insertions(+), 87 deletions(-) diff --git a/test/abilities/magic_guard.test.ts b/test/abilities/magic_guard.test.ts index ecadda17562..b346485c4a8 100644 --- a/test/abilities/magic_guard.test.ts +++ b/test/abilities/magic_guard.test.ts @@ -6,7 +6,6 @@ import { ArenaTagType } from "#enums/arena-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { Stat } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; import { WeatherType } from "#enums/weather-type"; import GameManager from "#test/testUtils/gameManager"; @@ -42,9 +41,9 @@ describe("Abilities - Magic Guard", () => { .enemyLevel(100); }); - //Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(Ability) + // Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(Ability) - it("ability should prevent damage caused by weather", async () => { + it("should prevent passive weather damage", async () => { game.override.weather(WeatherType.SANDSTORM); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -67,35 +66,7 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); }); - it("should retain catch boost, toxic turn count and burn attack drops", async () => { - game.override.statusEffect(StatusEffect.TOXIC); - await game.classicMode.startBattle([Species.MAGIKARP]); - - const leadPokemon = game.scene.getPlayerPokemon()!; - - game.move.select(Moves.SPLASH); - await game.phaseInterceptor.to("TurnEndPhase"); - - expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); - expect(leadPokemon.status).toBeTruthy(); - expect(leadPokemon.status!.toxicTurnCount).toBeGreaterThan(0); - expect(getStatusEffectCatchRateMultiplier(leadPokemon.status!.effect)).toBe(1.5); - - await game.toNextTurn(); - - // give ourselves burn and ensure our attack indeed dropped - - const prevAtk = leadPokemon.getEffectiveStat(Stat.ATK); - leadPokemon.resetStatus(); - expect(leadPokemon.status).toBeFalsy(); - - leadPokemon.trySetStatus(StatusEffect.BURN); - expect(leadPokemon.status).toBeTruthy(); - const burntAtk = leadPokemon.getEffectiveStat(Stat.ATK); - expect(burntAtk).toBeCloseTo(prevAtk / 2, 1); - }); - - it("ability effect should not persist when the ability is replaced", async () => { + it("should not persist when ability is replaced", async () => { game.override.enemyMoveset(Moves.WORRY_SEED).statusEffect(StatusEffect.POISON); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -113,53 +84,58 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents damage caused by burn but other non-damaging effects are still applied", async () => { - game.override.enemyStatusEffect(StatusEffect.BURN).enemyAbility(Abilities.MAGIC_GUARD); - - await game.classicMode.startBattle([Species.MAGIKARP]); - - game.move.select(Moves.SPLASH); + it("should prevent burn damage but not attack drop", async () => { + game.override + .moveset(Moves.WILL_O_WISP) + .enemyMoveset(Moves.TACKLE) + .enemyAbility(Abilities.MAGIC_GUARD) + .enemyPassiveAbility(Abilities.NO_GUARD); + await game.classicMode.startBattle([Species.GRANBULL]); + const granbull = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; + // Take 1 attack before being burned & 1 after + game.move.select(Moves.WILL_O_WISP); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to("TurnEndPhase"); - /** - * Expect: - * - The enemy Pokemon (with Magic Guard) has not taken damage from burn - * - The enemy Pokemon's physical attack damage is halved (TBD) - * - The enemy Pokemon's hypothetical CatchRateMultiplier should be 1.5 - */ + const firstTurnDmg = granbull.getInverseHp(); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); - expect(getStatusEffectCatchRateMultiplier(enemyPokemon.status!.effect)).toBe(1.5); + + await game.toNextTurn(); + + game.move.select(Moves.WILL_O_WISP); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + + const secondTurnDmg = granbull.getInverseHp() - firstTurnDmg; + expect(secondTurnDmg).toBeLessThan(firstTurnDmg); }); - it("Magic Guard prevents damage caused by toxic but other non-damaging effects are still applied", async () => { + it("should prevent non-volatile status damage without preventing other effects", async () => { game.override.enemyStatusEffect(StatusEffect.TOXIC).enemyAbility(Abilities.MAGIC_GUARD); - await game.classicMode.startBattle([Species.MAGIKARP]); - game.move.select(Moves.SPLASH); - const enemyPokemon = game.scene.getEnemyPokemon()!; - const toxicStartCounter = enemyPokemon.status!.toxicTurnCount; - //should be 0 + game.move.select(Moves.SPLASH); await game.phaseInterceptor.to("TurnEndPhase"); /** * Expect: * - The enemy Pokemon (with Magic Guard) has not taken damage from toxic * - The enemy Pokemon's status effect duration should be incremented - * - The enemy Pokemon's hypothetical CatchRateMultiplier should be 1.5 + * - The enemy Pokemon's CatchRateMultiplier should be 1.5 */ expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(enemyPokemon.status!.toxicTurnCount).toBeGreaterThan(toxicStartCounter); expect(getStatusEffectCatchRateMultiplier(enemyPokemon.status!.effect)).toBe(1.5); }); - it("Magic Guard prevents damage caused by entry hazards", async () => { + it("should prevent damage from entry hazards", async () => { //Adds and applies Spikes to both sides of the arena const newTag = getArenaTag(ArenaTagType.SPIKES, 5, Moves.SPIKES, 0, 0, ArenaTagSide.BOTH)!; game.scene.arena.tags.push(newTag); @@ -182,8 +158,8 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); }); - it("Magic Guard does not prevent poison from Toxic Spikes", async () => { - //Adds and applies Spikes to both sides of the arena + it("should not prevent Toxic Spikes from applying poison", async () => { + // Add Toxic Spikes to both sides of the arena const playerTag = getArenaTag(ArenaTagType.TOXIC_SPIKES, 5, Moves.TOXIC_SPIKES, 0, 0, ArenaTagSide.PLAYER)!; const enemyTag = getArenaTag(ArenaTagType.TOXIC_SPIKES, 5, Moves.TOXIC_SPIKES, 0, 0, ArenaTagSide.ENEMY)!; game.scene.arena.tags.push(playerTag); @@ -210,14 +186,13 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); }); - it("Magic Guard prevents against damage from volatile status effects", async () => { + it("should prevent damage from volatile status effects", async () => { await game.classicMode.startBattle([Species.DUSKULL]); game.override.moveset([Moves.CURSE]).enemyAbility(Abilities.MAGIC_GUARD); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.CURSE); - const enemyPokemon = game.scene.getEnemyPokemon()!; await game.phaseInterceptor.to("TurnEndPhase"); @@ -233,7 +208,7 @@ describe("Abilities - Magic Guard", () => { expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); }); - it("Magic Guard prevents crash damage", async () => { + it("should prevent crash damage", async () => { game.override.moveset([Moves.HIGH_JUMP_KICK]); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -251,7 +226,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents damage from recoil", async () => { + it("should prevent damage from recoil", async () => { game.override.moveset([Moves.TAKE_DOWN]); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -268,7 +243,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); }); - it("Magic Guard does not prevent damage from Struggle's recoil", async () => { + it("should not prevent damage from Struggle recoil", async () => { game.override.moveset([Moves.STRUGGLE]); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -331,7 +306,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents damage from abilities with PostTurnHurtIfSleepingAbAttr", async () => { + it("should prevent damage from abilities with PostTurnHurtIfSleepingAbAttr", async () => { game.override.statusEffect(StatusEffect.SLEEP).enemyMoveset(Moves.SPORE).enemyAbility(Abilities.BAD_DREAMS); await game.classicMode.startBattle([Species.MAGIKARP]); @@ -373,7 +348,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => { + it("should prevent damage from abilities with PostDefendContactDamageAbAttr", async () => { //Tests the abilities Iron Barbs/Rough Skin game.override.moveset([Moves.TACKLE]).enemyAbility(Abilities.IRON_BARBS); @@ -395,7 +370,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => { + it("should prevent damage from abilities with ReverseDrainAbAttr", async () => { //Tests the ability Liquid Ooze game.override.moveset([Moves.ABSORB]).enemyAbility(Abilities.LIQUID_OOZE); @@ -417,7 +392,7 @@ describe("Abilities - Magic Guard", () => { expect(leadPokemon.hp).toBe(leadPokemon.getMaxHp()); }); - it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => { + it("should prevent HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => { game.override.passiveAbility(Abilities.SOLAR_POWER).weather(WeatherType.SUNNY); await game.classicMode.startBattle([Species.MAGIKARP]); diff --git a/test/achievements/achievement.test.ts b/test/achievements/achievement.test.ts index ff66c8ba76b..5a74c77fe6a 100644 --- a/test/achievements/achievement.test.ts +++ b/test/achievements/achievement.test.ts @@ -130,7 +130,6 @@ describe("RibbonAchv", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([]).startingLevel(0).starterSpecies(0).enemyMoveset([]).enemySpecies(0).startingWave(0); scene = game.scene; }); diff --git a/test/battle/battle.test.ts b/test/battle/battle.test.ts index b0c3c70fbd9..374e673c04a 100644 --- a/test/battle/battle.test.ts +++ b/test/battle/battle.test.ts @@ -4,15 +4,12 @@ import { GameModes, getGameMode } from "#app/game-mode"; import { CommandPhase } from "#app/phases/command-phase"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; import { EncounterPhase } from "#app/phases/encounter-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { LoginPhase } from "#app/phases/login-phase"; import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; import { SelectGenderPhase } from "#app/phases/select-gender-phase"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { SelectStarterPhase } from "#app/phases/select-starter-phase"; import { SummonPhase } from "#app/phases/summon-phase"; import { TitlePhase } from "#app/phases/title-phase"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; import GameManager from "#test/testUtils/gameManager"; import { generateStarter } from "#test/testUtils/gameManagerUtils"; import { UiMode } from "#enums/ui-mode"; @@ -89,14 +86,15 @@ describe("Test - Battle Phase", () => { it("do attack wave 3 - single battle - regular - OHKO", async () => { game.override - .enemySpecies(Species.RATTATA) - .startingLevel(2000) - .startingWave(3) .battleStyle("single") - .enemyMoveset(Moves.TACKLE); + .startingWave(3) + .startingLevel(2000) + .moveset(Moves.TACKLE) + .enemySpecies(Species.RATTATA); await game.classicMode.startBattle([Species.MEWTWO]); + game.move.select(Moves.TACKLE); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false); + await game.toNextWave(); }); it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async () => { @@ -104,13 +102,14 @@ describe("Test - Battle Phase", () => { .enemySpecies(Species.RATTATA) .startingLevel(5) .startingWave(3) - .moveset([Moves.TACKLE]) + .moveset(Moves.TACKLE) .enemyAbility(Abilities.HYDRATION) .enemyMoveset(Moves.TAIL_WHIP) .battleStyle("single"); await game.classicMode.startBattle([Species.MEWTWO]); + game.move.select(Moves.TACKLE); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false); + await game.toNextWave(); }); it("load 100% data file", async () => { @@ -124,9 +123,11 @@ describe("Test - Battle Phase", () => { it("start battle with selected team", async () => { await game.classicMode.startBattle([Species.CHARIZARD, Species.CHANSEY, Species.MEW]); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(Species.CHARIZARD); - expect(game.scene.getPlayerParty()[1].species.speciesId).toBe(Species.CHANSEY); - expect(game.scene.getPlayerParty()[2].species.speciesId).toBe(Species.MEW); + expect(game.scene.getPlayerParty().map(pm => pm.species.speciesId)).toEqual([ + Species.CHARIZARD, + Species.CHANSEY, + Species.MEW, + ]); }); it("test remove random battle seed int", async () => { diff --git a/test/moves/instruct.test.ts b/test/moves/instruct.test.ts index 2cfe772208d..0325c230ccf 100644 --- a/test/moves/instruct.test.ts +++ b/test/moves/instruct.test.ts @@ -335,10 +335,9 @@ describe("Moves - Instruct", () => { game.move.select(Moves.ELECTRO_DRIFT); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to("FaintPhase"); - await game.move.changeMoveset[Moves.ELECTROWEB]; await game.toNextWave(); + game.move.changeMoveset(regieleki, [Moves.ELECTROWEB]); game.move.select(Moves.SPLASH); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to("TurnEndPhase", false); diff --git a/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts b/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts index c95f9dbb4bb..7b78a992ea4 100644 --- a/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts +++ b/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts @@ -137,7 +137,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(Species.GREEDENT); const moveset = enemyField[0].moveset.map(m => m.moveId); expect(moveset).toHaveLength(4); - expect(moveset).toEqual([Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH]); + expect(moveset).toEqual([Moves.THRASH, Moves.CRUNCH, Moves.BODY_PRESS, Moves.SLACK_OFF]); const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); expect(movePhases).toHaveLength(1); diff --git a/test/mystery-encounter/mystery-encounter-utils.test.ts b/test/mystery-encounter/mystery-encounter-utils.test.ts index c22d3d628a2..d0189c3604c 100644 --- a/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -51,7 +51,9 @@ describe("Mystery Encounter Utils", () => { game.override.seed("random"); let result = getRandomPlayerPokemon(); - expect(result.species.speciesId).toBe(Species.MANAPHY).seed("random2"); + expect(result.species.speciesId).toBe(Species.MANAPHY); + + game.override.seed("random2"); result = getRandomPlayerPokemon(); expect(result.species.speciesId).toBe(Species.ARCEUS); @@ -69,7 +71,9 @@ describe("Mystery Encounter Utils", () => { game.override.seed("random"); let result = getRandomPlayerPokemon(); - expect(result.species.speciesId).toBe(Species.MANAPHY).seed("random2"); + expect(result.species.speciesId).toBe(Species.MANAPHY); + + game.override.seed("random2"); result = getRandomPlayerPokemon(); expect(result.species.speciesId).toBe(Species.ARCEUS); @@ -86,7 +90,9 @@ describe("Mystery Encounter Utils", () => { game.override.seed("random"); let result = getRandomPlayerPokemon(true); - expect(result.species.speciesId).toBe(Species.MANAPHY).seed("random2"); + expect(result.species.speciesId).toBe(Species.MANAPHY); + + game.override.seed("random2"); result = getRandomPlayerPokemon(true); expect(result.species.speciesId).toBe(Species.MANAPHY); @@ -103,7 +109,9 @@ describe("Mystery Encounter Utils", () => { game.override.seed("random"); let result = getRandomPlayerPokemon(true, false); - expect(result.species.speciesId).toBe(Species.MANAPHY).seed("random2"); + expect(result.species.speciesId).toBe(Species.MANAPHY); + + game.override.seed("random2"); result = getRandomPlayerPokemon(true, false); expect(result.species.speciesId).toBe(Species.MANAPHY); @@ -120,7 +128,9 @@ describe("Mystery Encounter Utils", () => { game.override.seed("random"); let result = getRandomPlayerPokemon(true, false, true); - expect(result.species.speciesId).toBe(Species.ARCEUS).seed("random2"); + expect(result.species.speciesId).toBe(Species.ARCEUS); + + game.override.seed("random2"); result = getRandomPlayerPokemon(true, false, true); expect(result.species.speciesId).toBe(Species.ARCEUS); @@ -240,6 +250,7 @@ describe("Mystery Encounter Utils", () => { it("gets species of specified types", () => { // Only 9 tiers are: Kyogre, Groudon, Rayquaza, Arceus, Zacian, Koraidon, Miraidon, Terapagos + // TODO: This has to be changed const result = getRandomSpeciesByStarterCost(9, undefined, [PokemonType.GROUND]); const pokeSpecies = getPokemonSpecies(result); expect(pokeSpecies.speciesId).toBe(Species.GROUDON); diff --git a/test/testUtils/helpers/moveHelper.ts b/test/testUtils/helpers/moveHelper.ts index 9dc197be0e8..fa3c13c6dc2 100644 --- a/test/testUtils/helpers/moveHelper.ts +++ b/test/testUtils/helpers/moveHelper.ts @@ -18,6 +18,7 @@ export class MoveHelper extends GameManagerHelper { /** * Intercepts {@linkcode MoveEffectPhase} and mocks the phase's move's * accuracy to -1, guaranteeing a hit. + * @returns A promise that resolves once the next MoveEffectPhase has been reached (not run). */ public async forceHit(): Promise { await this.game.phaseInterceptor.to(MoveEffectPhase, false); @@ -28,7 +29,8 @@ export class MoveHelper extends GameManagerHelper { /** * Intercepts {@linkcode MoveEffectPhase} and mocks the phase's move's accuracy * to 0, guaranteeing a miss. - * @param firstTargetOnly - Whether the move should force miss on the first target only, in the case of multi-target moves. + * @param firstTargetOnly - Whether to only force a miss on the first target hit; default `false`. + * @returns A promise that resolves once the next MoveEffectPhase has been reached (not run). */ public async forceMiss(firstTargetOnly = false): Promise { await this.game.phaseInterceptor.to(MoveEffectPhase, false);