From 1b07a1aa2293439cc0da0a2bd0dc50688b1a7dfb Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Wed, 20 Aug 2025 17:16:39 -0400 Subject: [PATCH] Added tests for stone axe --- test/moves/ceaseless-edge-stone-axe.test.ts | 95 +++++++++++++++++ test/moves/ceaseless-edge.test.ts | 108 -------------------- test/moves/destiny-bond.test.ts | 4 +- 3 files changed, 96 insertions(+), 111 deletions(-) create mode 100644 test/moves/ceaseless-edge-stone-axe.test.ts delete mode 100644 test/moves/ceaseless-edge.test.ts diff --git a/test/moves/ceaseless-edge-stone-axe.test.ts b/test/moves/ceaseless-edge-stone-axe.test.ts new file mode 100644 index 00000000000..6355ab4813a --- /dev/null +++ b/test/moves/ceaseless-edge-stone-axe.test.ts @@ -0,0 +1,95 @@ +import { AbilityId } from "#enums/ability-id"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { MoveId } from "#enums/move-id"; +import { MoveResult } from "#enums/move-result"; +import { SpeciesId } from "#enums/species-id"; +import { GameManager } from "#test/test-utils/game-manager"; +import type { EntryHazardTagType } from "#types/arena-tags"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe.each<{ name: string; move: MoveId; hazard: EntryHazardTagType; hazardName: string }>([ + { name: "Ceaseless Edge", move: MoveId.CEASELESS_EDGE, hazard: ArenaTagType.SPIKES, hazardName: "spikes" }, + { name: "Stone Axe", move: MoveId.STONE_AXE, hazard: ArenaTagType.STEALTH_ROCK, hazardName: "stealth rock" }, +])("Move - $name", ({ move, hazard, hazardName }) => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleStyle("single") + .enemySpecies(SpeciesId.RATTATA) + .ability(AbilityId.NO_GUARD) + .enemyAbility(AbilityId.BALL_FETCH) + .enemyMoveset(MoveId.SPLASH) + .startingLevel(100) + .enemyLevel(100); + }); + + it(`should hit and apply ${hazardName}`, async () => { + await game.classicMode.startBattle([SpeciesId.ILLUMISE]); + + game.move.use(move); + await game.phaseInterceptor.to("MoveEffectPhase", false); + + // Spikes should not have any layers before move effect is applied + expect(game).not.toHaveArenaTag(hazard, ArenaTagSide.ENEMY); + + await game.toEndOfTurn(); + + expect(game).toHaveArenaTag({ tagType: hazard, side: ArenaTagSide.ENEMY, layers: 1 }); + expect(game.field.getEnemyPokemon()).not.toHaveFullHp(); + }); + + const maxLayers = hazard === ArenaTagType.SPIKES ? 3 : 1; + + it(`should not fail if ${hazardName} already has ${maxLayers} layer${maxLayers === 1 ? "" : "s"}`, async () => { + await game.classicMode.startBattle([SpeciesId.ILLUMISE]); + + for (let i = 0; i < maxLayers; i++) { + game.scene.arena.addTag(hazard, 0, undefined, 0, ArenaTagSide.ENEMY); + } + expect(game).toHaveArenaTag({ tagType: hazard, side: ArenaTagSide.ENEMY, layers: maxLayers }); + + game.move.use(move); + await game.toEndOfTurn(); + + // Should not have increased due to already being at max layers + expect(game).toHaveArenaTag({ tagType: hazard, side: ArenaTagSide.ENEMY, layers: maxLayers }); + const illumise = game.field.getPlayerPokemon(); + expect(illumise).toHaveUsedMove({ move, result: MoveResult.SUCCESS }); + expect(game.field.getEnemyPokemon()).not.toHaveFullHp(); + }); + + it.runIf(move === MoveId.CEASELESS_EDGE)( + "should apply 1 layer of spikes per hit when given multiple hits", + async () => { + game.override.startingHeldItems([{ name: "MULTI_LENS" }]); + await game.classicMode.startBattle([SpeciesId.ILLUMISE]); + + game.move.use(MoveId.CEASELESS_EDGE); + await game.phaseInterceptor.to("MoveEffectPhase"); + + // Hit 1 + expect(game).toHaveArenaTag({ tagType: ArenaTagType.SPIKES, side: ArenaTagSide.ENEMY, layers: 1 }); + + await game.toEndOfTurn(); + + // Hit 2 + expect(game).toHaveArenaTag({ tagType: ArenaTagType.SPIKES, side: ArenaTagSide.ENEMY, layers: 2 }); + expect(game.field.getEnemyPokemon()).not.toHaveFullHp(); + }, + ); +}); diff --git a/test/moves/ceaseless-edge.test.ts b/test/moves/ceaseless-edge.test.ts deleted file mode 100644 index b06ea84308c..00000000000 --- a/test/moves/ceaseless-edge.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { EntryHazardTag } from "#data/arena-tag"; -import { allMoves } from "#data/data-lists"; -import { AbilityId } from "#enums/ability-id"; -import { ArenaTagSide } from "#enums/arena-tag-side"; -import { ArenaTagType } from "#enums/arena-tag-type"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { MoveEffectPhase } from "#phases/move-effect-phase"; -import { TurnEndPhase } from "#phases/turn-end-phase"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - -describe("Moves - Ceaseless Edge", () => { - let phaserGame: Phaser.Game; - let game: GameManager; - - beforeAll(() => { - phaserGame = new Phaser.Game({ - type: Phaser.HEADLESS, - }); - }); - - afterEach(() => { - game.phaseInterceptor.restoreOg(); - }); - - beforeEach(() => { - game = new GameManager(phaserGame); - game.override - .battleStyle("single") - .enemySpecies(SpeciesId.RATTATA) - .enemyAbility(AbilityId.RUN_AWAY) - .enemyPassiveAbility(AbilityId.RUN_AWAY) - .startingLevel(100) - .enemyLevel(100) - .moveset([MoveId.CEASELESS_EDGE, MoveId.SPLASH, MoveId.ROAR]) - .enemyMoveset(MoveId.SPLASH); - vi.spyOn(allMoves[MoveId.CEASELESS_EDGE], "accuracy", "get").mockReturnValue(100); - }); - - test("move should hit and apply spikes", async () => { - await game.classicMode.startBattle([SpeciesId.ILLUMISE]); - - const enemyPokemon = game.field.getEnemyPokemon(); - - const enemyStartingHp = enemyPokemon.hp; - - game.move.select(MoveId.CEASELESS_EDGE); - - await game.phaseInterceptor.to(MoveEffectPhase, false); - // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); - - await game.phaseInterceptor.to(TurnEndPhase); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); - expect(tagAfter.layers).toBe(1); - expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); - }); - - test("move should hit twice with multi lens and apply two layers of spikes", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS" }]); - await game.classicMode.startBattle([SpeciesId.ILLUMISE]); - - const enemyPokemon = game.field.getEnemyPokemon(); - - const enemyStartingHp = enemyPokemon.hp; - - game.move.select(MoveId.CEASELESS_EDGE); - - await game.phaseInterceptor.to(MoveEffectPhase, false); - // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); - - await game.phaseInterceptor.to(TurnEndPhase); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); - expect(tagAfter.layers).toBe(2); - expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); - }); - - test("trainer - move should hit twice, apply two layers of spikes, force switch opponent - opponent takes damage", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS" }]).startingWave(25); - - await game.classicMode.startBattle([SpeciesId.ILLUMISE]); - - game.move.select(MoveId.CEASELESS_EDGE); - await game.phaseInterceptor.to(MoveEffectPhase, false); - // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); - - await game.toNextTurn(); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); - expect(tagAfter.layers).toBe(2); - - const hpBeforeSpikes = game.scene.currentBattle.enemyParty[1].hp; - // Check HP of pokemon that WILL BE switched in (index 1) - game.forceEnemyToSwitch(); - game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase, false); - expect(game.scene.currentBattle.enemyParty[0].hp).toBeLessThan(hpBeforeSpikes); - }); -}); diff --git a/test/moves/destiny-bond.test.ts b/test/moves/destiny-bond.test.ts index 118a45e7682..49093363325 100644 --- a/test/moves/destiny-bond.test.ts +++ b/test/moves/destiny-bond.test.ts @@ -195,9 +195,7 @@ describe("Moves - Destiny Bond", () => { expect(playerPokemon.isFainted()).toBe(true); // Ceaseless Edge spikes effect should still activate - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; - expect(tagAfter.tagType).toBe(ArenaTagType.SPIKES); - expect(tagAfter.layers).toBe(1); + expect(game).toHaveArenaTag({ tagType: ArenaTagType.SPIKES, side: ArenaTagSide.ENEMY, layers: 1 }); }); it("should not cause a crash if the user is KO'd by Pledge moves", async () => {