From 38cafe7b2729942de6ab3b28033fd8975da021cc Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Wed, 10 Sep 2025 13:48:50 -0400 Subject: [PATCH] Fixed type error + removed broken util --- test/arena/arena-tags.test.ts | 91 +++++++++++++++++---------------- test/test-utils/string-utils.ts | 51 ++++-------------- 2 files changed, 59 insertions(+), 83 deletions(-) diff --git a/test/arena/arena-tags.test.ts b/test/arena/arena-tags.test.ts index f4086cdd01d..9e1eb4d7fb8 100644 --- a/test/arena/arena-tags.test.ts +++ b/test/arena/arena-tags.test.ts @@ -6,7 +6,8 @@ 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 { getEnumTestCases } from "#test/test-utils/string-utils"; +import { getEnumStr } from "#test/test-utils/string-utils"; +import { getEnumValues } from "#utils/enums"; import { toTitleCase } from "#utils/strings"; import i18next from "i18next"; import Phaser from "phaser"; @@ -53,49 +54,53 @@ describe("Arena Tags", () => { // These tags are either ineligible or just jaaaaaaaaaaank const FORBIDDEN_TAGS = [ArenaTagType.NONE, ArenaTagType.NEUTRALIZING_GAS] as const; + const sides = getEnumValues(ArenaTagSide); const arenaTags = Object.values(ArenaTagType) .filter(t => !(FORBIDDEN_TAGS as readonly ArenaTagType[]).includes(t)) - .map(t => ({ - tagType: t, - name: toTitleCase(t), - })); - describe.each(arenaTags)("$name", ({ tagType }) => { - it.each(getEnumTestCases(ArenaTagSide))( - "should display a message on addition, and a separate one on removal - ArenaTagSide.$name", - ({ value: 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.clearLogs(); - - game.scene.arena.removeTagOnSide(tagType, side, false); - if (tag["onRemoveMessageKey"]) { - // TODO: Convert to `game.toHaveShownMessage` - 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); - }, + .flatMap(t => + sides.map(side => ({ + tagType: t, + name: toTitleCase(t), + side, + sideName: getEnumStr(ArenaTagSide, side), + })), ); - }); + + it.each(arenaTags)( + "$name should display a message on addition, and a separate one on removal - $sideName", + ({ tagType, 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.clearLogs(); + + game.scene.arena.removeTagOnSide(tagType, side, false); + if (tag["onRemoveMessageKey"]) { + // TODO: Convert to `game.toHaveShownMessage` + 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); + }, + ); }); diff --git a/test/test-utils/string-utils.ts b/test/test-utils/string-utils.ts index 8b953ac4742..281a8ce0a41 100644 --- a/test/test-utils/string-utils.ts +++ b/test/test-utils/string-utils.ts @@ -1,7 +1,7 @@ import { getStatKey, type Stat } from "#enums/stat"; import type { EnumOrObject, NormalEnum, TSNumericEnum } from "#types/enum-types"; import type { ObjectValues } from "#types/type-helpers"; -import { enumValueToKey, getEnumValues } from "#utils/enums"; +import { enumValueToKey } from "#utils/enums"; import { toTitleCase } from "#utils/strings"; import type { MatcherState } from "@vitest/expect"; import i18next from "i18next"; @@ -24,15 +24,18 @@ interface getEnumStrOptions { * If present, will be added to the end of the enum string. */ suffix?: string; + /** + * Whether to omit the value from the text. + * @defaultValue Whether `E` is a non-string enum + */ + omitValue?: boolean; } /** * Return the name of an enum member or const object value, alongside its corresponding value. * @param obj - The {@linkcode EnumOrObject} to source reverse mappings from - * @param enums - One of {@linkcode obj}'s values - * @param casing - A string denoting the casing method to use; default `Preserve` - * @param prefix - An optional string to be prepended to the enum's string representation - * @param suffix - An optional string to be appended to the enum's string representation + * @param val - One of {@linkcode obj}'s values + * @param options - Options modifying the stringification process. * @returns The stringified representation of `val` as dictated by the options. * @example * ```ts @@ -48,8 +51,9 @@ interface getEnumStrOptions { export function getEnumStr( obj: E, val: ObjectValues, - { casing = "Preserve", prefix = "", suffix = "" }: getEnumStrOptions = {}, + options: getEnumStrOptions = {}, ): string { + const { casing = "Preserve", prefix = "", suffix = "", omitValue = typeof val === "number" } = options; let casingFunc: ((s: string) => string) | undefined; switch (casing) { case "Preserve": @@ -70,7 +74,7 @@ export function getEnumStr( stringPart = casingFunc(stringPart); } - return `${prefix}${stringPart}${suffix} (=${val})`; + return `${prefix}${stringPart}${suffix}${omitValue ? ` (=${val})` : ""}`; } /** @@ -187,36 +191,3 @@ export function getOnelineDiffStr(this: MatcherState, obj: unknown): string { .replace(/\n/g, " ") // Replace newlines with spaces .replace(/,(\s*)\}$/g, "$1}"); // Trim trailing commas } - -/** - * Convert an enum or `const object` into an array of object literals - * suitable for use inside {@linkcode describe.each} or {@linkcode it.each}. - * @param obj - The {@linkcode EnumOrObject} to source reverse mappings from - * @param values - An array containing one or more of `obj`'s values to convert. - * Defaults to all the enum's values. - * @param options - Options to pass to {@linkcode getEnumStr} - * @returns An array of objects containing the enum's name and value. - * @example - * ```ts - * enum fakeEnum { - * ONE: 1, - * TWO: 2, - * THREE: 3, - * } - * describe.each(getEnumTestCases(fakeEnum))("should do XYZ - $name", ({value}) => {}); - * ``` - */ -export function getEnumTestCases( - obj: E, - values: E[keyof E][] = isTSNumericEnum(obj) ? getEnumValues(obj) : (Object.values(obj) as E[keyof E][]), - options: getEnumStrOptions = {}, -): { value: E[keyof E]; name: string }[] { - return values.map(e => ({ - value: e, - name: getEnumStr(obj, e, options), - })); -} - -function isTSNumericEnum(obj: E): obj is TSNumericEnum { - return Object.keys(obj).some(k => typeof k === "number"); -}