Fixed up the tests for locale messages + fixed lucky chant

This commit is contained in:
Bertie690 2025-08-20 19:25:16 -04:00
parent ac080588e9
commit 1a99b08a9d
4 changed files with 111 additions and 19 deletions

View File

@ -624,7 +624,7 @@ export class NoCritTag extends SerializableArenaTag {
return "arenaTag:noCritOnAdd" + this.i18nSideKey;
}
protected override get onRemoveMessageKey(): string {
return "arenaTag:noCritOnRemove";
return "arenaTag:noCritOnRemove" + this.i18nSideKey;
}
public override apply(blockCrit: BooleanHolder): void {

View File

@ -0,0 +1,97 @@
import { getPokemonNameWithAffix } from "#app/messages";
import { AbilityId } from "#enums/ability-id";
import { ArenaTagSide } from "#enums/arena-tag-side";
import { ArenaTagType } from "#enums/arena-tag-type";
import { BattleType } from "#enums/battle-type";
import { MoveId } from "#enums/move-id";
import { SpeciesId } from "#enums/species-id";
import { GameManager } from "#test/test-utils/game-manager";
import { getEnumValues } from "#utils/enums";
import { toTitleCase } from "#utils/strings";
import i18next from "i18next";
import Phaser from "phaser";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("Arena Tags", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
let playerId: number;
afterAll(() => {
game.phaseInterceptor.restoreOg();
});
beforeAll(async () => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
game = new GameManager(phaserGame);
game.override
.battleStyle("single")
.enemySpecies(SpeciesId.BLISSEY)
.startingLevel(100)
.enemyLevel(100)
.enemyAbility(AbilityId.BALL_FETCH)
.ability(AbilityId.BALL_FETCH)
.enemyMoveset(MoveId.SPLASH)
.battleType(BattleType.TRAINER);
await game.classicMode.startBattle([SpeciesId.MORELULL]);
playerId = game.field.getPlayerPokemon().id;
});
beforeEach(() => {
// Mock the message queue function to not unshift phases and just spit the text out directly
vi.spyOn(game.scene.phaseManager, "queueMessage").mockImplementation((text, callbackDelay, prompt, promptDelay) =>
game.scene.ui.showText(text, null, null, callbackDelay, prompt, promptDelay),
);
game.textInterceptor.logs = [];
});
const arenaTags = Object.values(ArenaTagType)
.filter(t => t !== ArenaTagType.NONE)
.map(t => ({
tagType: t,
name: toTitleCase(t),
}));
describe.each(arenaTags)("$name", ({ tagType }) => {
it.each(getEnumValues(ArenaTagSide))(
"should display a message on addition, and a separate one on removal",
side => {
game.scene.arena.addTag(tagType, 0, undefined, playerId, side);
expect(game).toHaveArenaTag(tagType, side);
const tag = game.scene.arena.getTagOnSide(tagType, side)!;
if (tag["onAddMessageKey"]) {
expect(game.textInterceptor.logs).toContain(
i18next.t(tag["onAddMessageKey"], {
pokemonNameWithAffix: getPokemonNameWithAffix(tag["getSourcePokemon"]()),
moveName: tag["getMoveName"](),
}),
);
} else {
expect(game.textInterceptor.logs).toHaveLength(0);
}
game.textInterceptor.logs = [];
game.scene.arena.removeTagOnSide(tagType, side, false);
if (tag["onRemoveMessageKey"]) {
expect(game.textInterceptor.logs).toContain(
i18next.t(tag["onRemoveMessageKey"], {
pokemonNameWithAffix: getPokemonNameWithAffix(tag["getSourcePokemon"]()),
moveName: tag["getMoveName"](),
}),
);
} else {
expect(game.textInterceptor.logs).toHaveLength(0);
}
expect(game).not.toHaveArenaTag(tagType, side);
},
);
});
});

View File

@ -1,5 +1,4 @@
import { getPokemonNameWithAffix } from "#app/messages";
import { allMoves } from "#data/data-lists";
import type { TypeDamageMultiplier } from "#data/type";
import { AbilityId } from "#enums/ability-id";
import { ArenaTagSide } from "#enums/arena-tag-side";
@ -147,7 +146,7 @@ describe("Moves - Entry Hazards", () => {
it.each<{ name: string; layers: number; status: StatusEffect }>([
{ name: "Poison", layers: 1, status: StatusEffect.POISON },
{ name: "Toxic", layers: 2, status: StatusEffect.TOXIC },
])("should apply $name at $layers without displaying neutralization msg", async ({ layers, status }) => {
])("should apply $name at $layers", async ({ layers, status }) => {
for (let i = 0; i < layers; i++) {
game.scene.arena.addTag(ArenaTagType.TOXIC_SPIKES, 0, undefined, 0, ArenaTagSide.ENEMY);
}
@ -155,31 +154,20 @@ describe("Moves - Entry Hazards", () => {
const enemy = game.field.getEnemyPokemon();
expect(enemy).toHaveStatusEffect(status);
expect(game.textInterceptor.logs).not.toContain(
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
pokemonNameWithAffix: getPokemonNameWithAffix(enemy),
moveName: allMoves[MoveId.TOXIC_SPIKES].name,
}),
);
});
});
it("should be removed without triggering upon a grounded Poison-type switching in", async () => {
it("should be removed upon a grounded Poison-type switching in", async () => {
await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.EKANS]);
game.scene.arena.addTag(ArenaTagType.TOXIC_SPIKES, 0, undefined, 0, ArenaTagSide.ENEMY);
game.scene.arena.addTag(ArenaTagType.TOXIC_SPIKES, 0, undefined, 0, ArenaTagSide.PLAYER);
game.doSwitchPokemon(1);
await game.toNextTurn();
const ekans = game.field.getPlayerPokemon();
expect(game).not.toHaveArenaTag(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.PLAYER);
expect(game.textInterceptor.logs).not.toContain(
i18next.t("arenaTag:toxicSpikesActivateTrapPoison", {
pokemonNameWithAffix: getPokemonNameWithAffix(ekans),
moveName: allMoves[MoveId.TOXIC_SPIKES].name,
}),
);
expect(game.textInterceptor.logs).toContain(i18next.t("arenaTag:toxicSpikesOnRemovePlayer"));
expect(ekans).not.toHaveStatusEffect(StatusEffect.POISON);
});
@ -200,7 +188,7 @@ describe("Moves - Entry Hazards", () => {
expect(enemy).toHaveTakenDamage(enemy.getMaxHp() * 0.125 * multi);
expect(game.textInterceptor.logs).toContain(
i18next.t("arenaTag:stealthRockActivateTrap", {
pokemonName: getPokemonNameWithAffix(enemy),
pokemonNameWithAffix: getPokemonNameWithAffix(enemy),
}),
);
});
@ -225,7 +213,7 @@ describe("Moves - Entry Hazards", () => {
expect(enemy).toHaveStatStage(Stat.SPD, -1);
expect(game.textInterceptor.logs).toContain(
i18next.t("arenaTag:stickyWebActivateTrap", {
pokemonName: enemy.getNameToRender(),
pokemonNameWithAffix: getPokemonNameWithAffix(enemy),
}),
);
});

View File

@ -1,3 +1,4 @@
import { allMoves } from "#data/data-lists";
import { AbilityId } from "#enums/ability-id";
import { MoveId } from "#enums/move-id";
import { SpeciesId } from "#enums/species-id";
@ -6,6 +7,7 @@ import { BerryPhase } from "#phases/berry-phase";
import { CommandPhase } from "#phases/command-phase";
import { TurnEndPhase } from "#phases/turn-end-phase";
import { GameManager } from "#test/test-utils/game-manager";
import i18next from "i18next";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest";
@ -47,6 +49,11 @@ describe("Moves - Mat Block", () => {
await game.phaseInterceptor.to(BerryPhase, false);
leadPokemon.forEach(p => expect(p.hp).toBe(p.getMaxHp()));
expect(game.textInterceptor.logs).toContain(
i18next.t("arenaTags:matBlockApply", {
attackName: allMoves[MoveId.TACKLE].name,
}),
);
});
test("should not protect the user and allies from status moves", async () => {