mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-14 19:39:29 +02:00
Fixed log message to not be overly verbose
This commit is contained in:
parent
3a6a16f3ff
commit
4b447073a7
8
global.d.ts
vendored
8
global.d.ts
vendored
@ -1,3 +1,4 @@
|
|||||||
|
import type { AnyFn } from "#types/type-helpers";
|
||||||
import type { SetupServerApi } from "msw/node";
|
import type { SetupServerApi } from "msw/node";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -9,4 +10,11 @@ declare global {
|
|||||||
* To set up your own server in a test see `game-data.test.ts`
|
* To set up your own server in a test see `game-data.test.ts`
|
||||||
*/
|
*/
|
||||||
var server: SetupServerApi;
|
var server: SetupServerApi;
|
||||||
|
|
||||||
|
// Overloads for `Function.apply` and `Function.call` to add type safety on matching argument types
|
||||||
|
interface Function {
|
||||||
|
apply<T extends AnyFn>(this: T, thisArg: ThisParameterType<T>, argArray: Parameters<T>): ReturnType<T>;
|
||||||
|
|
||||||
|
call<T extends AnyFn>(this: T, thisArg: ThisParameterType<T>, ...argArray: Parameters<T>): ReturnType<T>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { getOnelineDiffStr } from "#test/test-utils/string-utils";
|
||||||
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,17 +29,20 @@ export function toEqualArrayUnsorted(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create shallow copies of the arrays in case we have
|
// Create shallow copies of the arrays in case we have
|
||||||
const gotSorted = received.slice().sort();
|
const actualSorted = received.slice().sort();
|
||||||
const wantSorted = expected.slice().sort();
|
const expectedSorted = expected.slice().sort();
|
||||||
const pass = this.equals(gotSorted, wantSorted, [...this.customTesters, this.utils.iterableEquality]);
|
const pass = this.equals(actualSorted, expectedSorted, [...this.customTesters, this.utils.iterableEquality]);
|
||||||
|
|
||||||
|
const actualStr = getOnelineDiffStr.call(this, actualSorted);
|
||||||
|
const expectedStr = getOnelineDiffStr.call(this, expectedSorted);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pass,
|
pass,
|
||||||
message: () =>
|
message: () =>
|
||||||
pass
|
pass
|
||||||
? `Expected ${this.utils.stringify(received)} to NOT exactly equal ${this.utils.stringify(expected)} without order!`
|
? `Expected ${actualStr} to NOT exactly equal ${expectedStr} without order, but it did!`
|
||||||
: `Expected ${this.utils.stringify(received)} to exactly equal ${this.utils.stringify(expected)} without order!`,
|
: `Expected ${actualStr} to exactly equal ${expectedStr} without order, but it didn't!`,
|
||||||
expected: wantSorted,
|
expected: expectedSorted,
|
||||||
actual: gotSorted,
|
actual: actualSorted,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,14 @@ export function toHaveBattlerTag(
|
|||||||
const pass = !!received.getTag(expectedBattlerTagType);
|
const pass = !!received.getTag(expectedBattlerTagType);
|
||||||
const pkmName = getPokemonNameWithAffix(received);
|
const pkmName = getPokemonNameWithAffix(received);
|
||||||
// "BattlerTagType.SEEDED (=1)"
|
// "BattlerTagType.SEEDED (=1)"
|
||||||
const expectedTagStr = getEnumStr(BattlerTagType, expectedBattlerTagType);
|
const expectedTagStr = getEnumStr(BattlerTagType, expectedBattlerTagType, { prefix: "BattlerTagType." });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pass,
|
pass,
|
||||||
message: () =>
|
message: () =>
|
||||||
pass
|
pass
|
||||||
? `Expected ${pkmName} to NOT have BattlerTagType.${expectedTagStr}, but it did!`
|
? `Expected ${pkmName} to NOT have ${expectedTagStr}, but it did!`
|
||||||
: `Expected ${pkmName} to have BattlerTagType.${expectedTagStr}, but it didn't!`,
|
: `Expected ${pkmName} to have ${expectedTagStr}, but it didn't!`,
|
||||||
expected: expectedBattlerTagType,
|
expected: expectedBattlerTagType,
|
||||||
actual: received.summonData.tags.map(t => t.tagType),
|
actual: received.summonData.tags.map(t => t.tagType),
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ export function toHaveStatStage(
|
|||||||
pass
|
pass
|
||||||
? `Expected ${pkmName}'s ${statName} stat stage to NOT be ${expectedStage}, but it was!`
|
? `Expected ${pkmName}'s ${statName} stat stage to NOT be ${expectedStage}, but it was!`
|
||||||
: `Expected ${pkmName}'s ${statName} stat stage to be ${expectedStage}, but got ${actualStage} instead!`,
|
: `Expected ${pkmName}'s ${statName} stat stage to be ${expectedStage}, but got ${actualStage} instead!`,
|
||||||
actual: actualStage,
|
|
||||||
expected: expectedStage,
|
expected: expectedStage,
|
||||||
|
actual: actualStage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import type { Pokemon } from "#field/pokemon";
|
|||||||
|
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { getEnumStr } from "#test/test-utils/string-utils";
|
import { getEnumStr, getOnelineDiffStr } from "#test/test-utils/string-utils";
|
||||||
import { isPokemonInstance, receivedStr } from "#test/test-utils/test-utils";
|
import { isPokemonInstance, receivedStr } from "#test/test-utils/test-utils";
|
||||||
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
import type { MatcherState, SyncExpectationResult } from "@vitest/expect";
|
||||||
|
|
||||||
@ -33,14 +33,20 @@ export function toHaveStatusEffect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pkmName = getPokemonNameWithAffix(received);
|
const pkmName = getPokemonNameWithAffix(received);
|
||||||
|
const actualEffect = received.status?.effect ?? StatusEffect.NONE;
|
||||||
|
|
||||||
// Check exclusively effect equality
|
// Check exclusively effect equality first, coercing non-matching status effects to numbers.
|
||||||
if (typeof expectedStatus === "number" || received.status?.effect !== expectedStatus.effect) {
|
if (actualEffect !== (expectedStatus as Exclude<typeof expectedStatus, StatusEffect>)?.effect) {
|
||||||
const actualEffect = received.status?.effect ?? StatusEffect.NONE;
|
// This is actually 100% safe as `expectedStatus?.effect` will evaluate to `undefined` if a StatusEffect was passed,
|
||||||
|
// which will never match actualEffect by definition
|
||||||
|
expectedStatus = (expectedStatus as Exclude<typeof expectedStatus, StatusEffect>).effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expectedStatus === "number") {
|
||||||
const pass = this.equals(actualEffect, expectedStatus, [...this.customTesters, this.utils.iterableEquality]);
|
const pass = this.equals(actualEffect, expectedStatus, [...this.customTesters, this.utils.iterableEquality]);
|
||||||
|
|
||||||
const actualStr = getEnumStr(StatusEffect, actualEffect, { prefix: "StatusEffect." });
|
const actualStr = getEnumStr(StatusEffect, actualEffect, { prefix: "StatusEffect." });
|
||||||
const expectedStr = getEnumStr(StatusEffect, actualEffect, { prefix: "StatusEffect." });
|
const expectedStr = getEnumStr(StatusEffect, expectedStatus, { prefix: "StatusEffect." });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pass,
|
pass,
|
||||||
@ -53,7 +59,7 @@ export function toHaveStatusEffect(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for equality of all fields (for toxic turn count)
|
// Check for equality of all fields (for toxic turn count/etc)
|
||||||
const actualStatus = received.status;
|
const actualStatus = received.status;
|
||||||
const pass = this.equals(received, expectedStatus, [
|
const pass = this.equals(received, expectedStatus, [
|
||||||
...this.customTesters,
|
...this.customTesters,
|
||||||
@ -61,12 +67,15 @@ export function toHaveStatusEffect(
|
|||||||
this.utils.iterableEquality,
|
this.utils.iterableEquality,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const expectedStr = getOnelineDiffStr.call(this, expectedStatus);
|
||||||
|
const actualStr = getOnelineDiffStr.call(this, actualStatus);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pass,
|
pass,
|
||||||
message: () =>
|
message: () =>
|
||||||
pass
|
pass
|
||||||
? `Expected ${pkmName}'s status to NOT match ${this.utils.stringify(expectedStatus)}, but it did!`
|
? `Expected ${pkmName}'s status to NOT match ${expectedStr}, but it did!`
|
||||||
: `Expected ${pkmName}'s status to match ${this.utils.stringify(expectedStatus)}, but got ${this.utils.stringify(actualStatus)} instead!`,
|
: `Expected ${pkmName}'s status to match ${expectedStr}, but got ${actualStr} instead!`,
|
||||||
expected: expectedStatus,
|
expected: expectedStatus,
|
||||||
actual: actualStatus,
|
actual: actualStatus,
|
||||||
};
|
};
|
||||||
|
@ -39,8 +39,8 @@ export function toHaveTerrain(
|
|||||||
pass
|
pass
|
||||||
? `Expected Arena to NOT have ${expectedStr} active, but it did!`
|
? `Expected Arena to NOT have ${expectedStr} active, but it did!`
|
||||||
: `Expected Arena to have ${expectedStr} active, but got ${actualStr} instead!`,
|
: `Expected Arena to have ${expectedStr} active, but got ${actualStr} instead!`,
|
||||||
actual,
|
|
||||||
expected: expectedTerrainType,
|
expected: expectedTerrainType,
|
||||||
|
actual,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,5 +53,6 @@ function toTerrainStr(terrainType: TerrainType) {
|
|||||||
if (terrainType === TerrainType.NONE) {
|
if (terrainType === TerrainType.NONE) {
|
||||||
return "no terrain";
|
return "no terrain";
|
||||||
}
|
}
|
||||||
|
// "Electric Terrain (=2)"
|
||||||
return getEnumStr(TerrainType, terrainType, { casing: "Title", suffix: " Terrain" });
|
return getEnumStr(TerrainType, terrainType, { casing: "Title", suffix: " Terrain" });
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ export function toHaveTypes(
|
|||||||
pass
|
pass
|
||||||
? `Expected ${pkmName} to NOT have types ${expectedStr}, but it did!`
|
? `Expected ${pkmName} to NOT have types ${expectedStr}, but it did!`
|
||||||
: `Expected ${pkmName} to have types ${expectedStr}, but got ${actualStr} instead!`,
|
: `Expected ${pkmName} to have types ${expectedStr}, but got ${actualStr} instead!`,
|
||||||
actual: actualTypes,
|
|
||||||
expected: expectedTypes,
|
expected: expectedTypes,
|
||||||
|
actual: actualTypes,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
|||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
// biome-ignore lint/correctness/noUnusedImports: TSDocs
|
// biome-ignore lint/correctness/noUnusedImports: TSDocs
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import { getOrdinal } from "#test/test-utils/string-utils";
|
import { getOnelineDiffStr, getOrdinal } from "#test/test-utils/string-utils";
|
||||||
import { isPokemonInstance, receivedStr } from "#test/test-utils/test-utils";
|
import { isPokemonInstance, receivedStr } from "#test/test-utils/test-utils";
|
||||||
import type { TurnMove } from "#types/turn-move";
|
import type { TurnMove } from "#types/turn-move";
|
||||||
import type { AtLeastOne } from "#types/type-helpers";
|
import type { AtLeastOne } from "#types/type-helpers";
|
||||||
@ -54,12 +54,14 @@ export function toHaveUsedMove(
|
|||||||
this.utils.iterableEquality,
|
this.utils.iterableEquality,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const expectedStr = getOnelineDiffStr.call(this, expectedResult);
|
||||||
return {
|
return {
|
||||||
pass,
|
pass,
|
||||||
message: () =>
|
message: () =>
|
||||||
pass
|
pass
|
||||||
? `Expected ${pkmName}'s ${moveIndexStr} to NOT match ${this.utils.stringify(expectedResult)}, but it did!`
|
? `Expected ${pkmName}'s ${moveIndexStr} to NOT match ${expectedStr}, but it did!`
|
||||||
: `Expected ${pkmName}'s ${moveIndexStr} to match ${this.utils.stringify(expectedResult)}, but got ${this.utils.stringify(move)} instead!`,
|
: // Replace newlines with spaces to preserve one-line ness
|
||||||
|
`Expected ${pkmName}'s ${moveIndexStr} to match ${expectedStr}, but it didn't!`,
|
||||||
expected: expectedResult,
|
expected: expectedResult,
|
||||||
actual: move,
|
actual: move,
|
||||||
};
|
};
|
||||||
|
@ -39,8 +39,8 @@ export function toHaveWeather(
|
|||||||
pass
|
pass
|
||||||
? `Expected Arena to NOT have ${expectedStr} weather active, but it did!`
|
? `Expected Arena to NOT have ${expectedStr} weather active, but it did!`
|
||||||
: `Expected Arena to have ${expectedStr} weather active, but got ${actualStr} instead!`,
|
: `Expected Arena to have ${expectedStr} weather active, but got ${actualStr} instead!`,
|
||||||
actual,
|
|
||||||
expected: expectedWeatherType,
|
expected: expectedWeatherType,
|
||||||
|
actual,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { getStatKey, type Stat } from "#enums/stat";
|
|||||||
import type { EnumOrObject, EnumValues, NormalEnum, TSNumericEnum } from "#types/enum-types";
|
import type { EnumOrObject, EnumValues, NormalEnum, TSNumericEnum } from "#types/enum-types";
|
||||||
import { enumValueToKey } 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 i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
type Casing = "Preserve" | "Title";
|
type Casing = "Preserve" | "Title";
|
||||||
@ -23,12 +24,12 @@ interface getEnumStrOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to 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 enums - One of {@linkcode obj}'s values
|
||||||
* @param casing - A string denoting the casing method to use; default `Preserve`
|
* @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 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 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
|
||||||
@ -37,8 +38,8 @@ interface getEnumStrOptions {
|
|||||||
* TWO: 2,
|
* TWO: 2,
|
||||||
* THREE: 3,
|
* THREE: 3,
|
||||||
* }
|
* }
|
||||||
* console.log(getEnumStr(fakeEnum, fakeEnum.ONE)); // Output: "ONE (=1)"
|
* getEnumStr(fakeEnum, fakeEnum.ONE); // Output: "ONE (=1)"
|
||||||
* console.log(getEnumStr(fakeEnum, fakeEnum.TWO, {case: "Title", prefix: "fakeEnum."})); // Output: "fakeEnum.Two (=2)"
|
* getEnumStr(fakeEnum, fakeEnum.TWO, {casing: "Title", prefix: "fakeEnum.", suffix: "!!!"}); // Output: "fakeEnum.TWO!!! (=2)"
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function getEnumStr<E extends EnumOrObject>(
|
export function getEnumStr<E extends EnumOrObject>(
|
||||||
@ -73,7 +74,7 @@ export function getEnumStr<E extends EnumOrObject>(
|
|||||||
* Convert an array of enums or `const object`s into a readable string version.
|
* Convert an array of enums or `const object`s into a readable string version.
|
||||||
* @param obj - The {@linkcode EnumOrObject} to source reverse mappings from
|
* @param obj - The {@linkcode EnumOrObject} to source reverse mappings from
|
||||||
* @param enums - An array of {@linkcode obj}'s values
|
* @param enums - An array of {@linkcode obj}'s values
|
||||||
* @returns The stringified representation of `enums`
|
* @returns The stringified representation of `enums`.
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* enum fakeEnum {
|
* enum fakeEnum {
|
||||||
@ -90,19 +91,49 @@ export function stringifyEnumArray<E extends EnumOrObject>(obj: E, enums: E[keyo
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vals = enums.slice();
|
const vals = enums.slice();
|
||||||
|
/** An array of string names */
|
||||||
let names: string[];
|
let names: string[];
|
||||||
|
|
||||||
if (obj[enums[0]] !== undefined) {
|
if (obj[enums[0]] !== undefined) {
|
||||||
// Reverse mapping exists - `obj` is a `TSNumericEnum` and its reverse mapped counterparts
|
// Reverse mapping exists - `obj` is a `TSNumericEnum` and its reverse mapped counterparts are strings
|
||||||
names = enums.map(e => (obj as TSNumericEnum<E>)[e] as string);
|
names = enums.map(e => (obj as TSNumericEnum<E>)[e] as string);
|
||||||
} else {
|
} else {
|
||||||
// No reverse mapping exists means `obj` is a `NormalEnum`
|
// No reverse mapping exists means `obj` is a `NormalEnum`.
|
||||||
names = enums.map(e => enumValueToKey(obj as NormalEnum<E>, e) as string);
|
// NB: This (while ugly) should be more ergonomic than doing a repeated lookup for large `const object`s
|
||||||
|
// as the `enums` array should be significantly shorter than the corresponding enum type.
|
||||||
|
names = [];
|
||||||
|
for (const [k, v] of Object.entries(obj as NormalEnum<E>)) {
|
||||||
|
if (names.length === enums.length) {
|
||||||
|
// No more names to get
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Find all matches for the given enum, assigning their keys to the names array
|
||||||
|
findIndices(enums, v).forEach(matchIndex => {
|
||||||
|
names[matchIndex] = k;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return `[${names.join(", ")}] (=[${vals.join(", ")}])`;
|
return `[${names.join(", ")}] (=[${vals.join(", ")}])`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the indices of all occurrences of a value in an array.
|
||||||
|
* @param arr - The array to search
|
||||||
|
* @param searchElement - The value to locate in the array
|
||||||
|
* @param fromIndex - The array index at which to begin the search. If fromIndex is omitted, the
|
||||||
|
* search starts at index 0
|
||||||
|
*/
|
||||||
|
function findIndices<T>(arr: T[], searchElement: T, fromIndex = 0): number[] {
|
||||||
|
const indices: number[] = [];
|
||||||
|
const arrSliced = arr.slice(fromIndex);
|
||||||
|
for (const [index, value] of arrSliced.entries()) {
|
||||||
|
if (value === searchElement) {
|
||||||
|
indices.push(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a number into an English ordinal
|
* Convert a number into an English ordinal
|
||||||
* @param num - The number to convert into an ordinal
|
* @param num - The number to convert into an ordinal
|
||||||
@ -137,3 +168,15 @@ export function getOrdinal(num: number): string {
|
|||||||
export function getStatName(s: Stat): string {
|
export function getStatName(s: Stat): string {
|
||||||
return i18next.t(getStatKey(s));
|
return i18next.t(getStatKey(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an object into a oneline diff to be shown in an error message.
|
||||||
|
* @param obj - The object to return the oneline diff of
|
||||||
|
* @returns The updated diff
|
||||||
|
*/
|
||||||
|
export function getOnelineDiffStr(this: MatcherState, obj: unknown): string {
|
||||||
|
return this.utils
|
||||||
|
.stringify(obj, undefined, { maxLength: 35, indent: 0, printBasicPrototype: false })
|
||||||
|
.replace(/\n/g, " ") // Replace newlines with spaces
|
||||||
|
.replace(/,(\s*)}$/g, "$1}");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user