Fixed type error + removed broken util

This commit is contained in:
Bertie690 2025-09-10 13:48:50 -04:00
parent 3780841e0d
commit 38cafe7b27
2 changed files with 59 additions and 83 deletions

View File

@ -6,7 +6,8 @@ import { BattleType } from "#enums/battle-type";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { GameManager } from "#test/test-utils/game-manager"; 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 { toTitleCase } from "#utils/strings";
import i18next from "i18next"; import i18next from "i18next";
import Phaser from "phaser"; import Phaser from "phaser";
@ -53,49 +54,53 @@ describe("Arena Tags", () => {
// These tags are either ineligible or just jaaaaaaaaaaank // These tags are either ineligible or just jaaaaaaaaaaank
const FORBIDDEN_TAGS = [ArenaTagType.NONE, ArenaTagType.NEUTRALIZING_GAS] as const; const FORBIDDEN_TAGS = [ArenaTagType.NONE, ArenaTagType.NEUTRALIZING_GAS] as const;
const sides = getEnumValues(ArenaTagSide);
const arenaTags = Object.values(ArenaTagType) const arenaTags = Object.values(ArenaTagType)
.filter(t => !(FORBIDDEN_TAGS as readonly ArenaTagType[]).includes(t)) .filter(t => !(FORBIDDEN_TAGS as readonly ArenaTagType[]).includes(t))
.map(t => ({ .flatMap(t =>
tagType: t, sides.map(side => ({
name: toTitleCase(t), tagType: t,
})); name: toTitleCase(t),
describe.each(arenaTags)("$name", ({ tagType }) => { side,
it.each(getEnumTestCases(ArenaTagSide))( sideName: getEnumStr(ArenaTagSide, side),
"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);
},
); );
});
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);
},
);
}); });

View File

@ -1,7 +1,7 @@
import { getStatKey, type Stat } from "#enums/stat"; import { getStatKey, type Stat } from "#enums/stat";
import type { EnumOrObject, NormalEnum, TSNumericEnum } from "#types/enum-types"; import type { EnumOrObject, NormalEnum, TSNumericEnum } from "#types/enum-types";
import type { ObjectValues } from "#types/type-helpers"; import type { ObjectValues } from "#types/type-helpers";
import { enumValueToKey, getEnumValues } from "#utils/enums"; import { enumValueToKey } from "#utils/enums";
import { toTitleCase } from "#utils/strings"; import { toTitleCase } from "#utils/strings";
import type { MatcherState } from "@vitest/expect"; import type { MatcherState } from "@vitest/expect";
import i18next from "i18next"; import i18next from "i18next";
@ -24,15 +24,18 @@ interface getEnumStrOptions {
* If present, will be added to the end of the enum string. * If present, will be added to the end of the enum string.
*/ */
suffix?: 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. * 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 obj - The {@linkcode EnumOrObject} to source reverse mappings from
* @param enums - One of {@linkcode obj}'s values * @param val - One of {@linkcode obj}'s values
* @param casing - A string denoting the casing method to use; default `Preserve` * @param options - Options modifying the stringification process.
* @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
* @returns The stringified representation of `val` as dictated by the options. * @returns The stringified representation of `val` as dictated by the options.
* @example * @example
* ```ts * ```ts
@ -48,8 +51,9 @@ interface getEnumStrOptions {
export function getEnumStr<E extends EnumOrObject>( export function getEnumStr<E extends EnumOrObject>(
obj: E, obj: E,
val: ObjectValues<E>, val: ObjectValues<E>,
{ casing = "Preserve", prefix = "", suffix = "" }: getEnumStrOptions = {}, options: getEnumStrOptions = {},
): string { ): string {
const { casing = "Preserve", prefix = "", suffix = "", omitValue = typeof val === "number" } = options;
let casingFunc: ((s: string) => string) | undefined; let casingFunc: ((s: string) => string) | undefined;
switch (casing) { switch (casing) {
case "Preserve": case "Preserve":
@ -70,7 +74,7 @@ export function getEnumStr<E extends EnumOrObject>(
stringPart = casingFunc(stringPart); 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(/\n/g, " ") // Replace newlines with spaces
.replace(/,(\s*)\}$/g, "$1}"); // Trim trailing commas .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<E extends EnumOrObject>(
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<E extends EnumOrObject>(obj: E): obj is TSNumericEnum<E> {
return Object.keys(obj).some(k => typeof k === "number");
}